题目

给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m

的模式串s,其中每一位仍然是A到z的大写字母。Alice希望知道,有多少对结点<u,v>满足T上从u到V的最短路径

形成的字符串可以由模式串S重复若干次得到?这里结点对<u,v>是有序的,也就是说<u,v>和<v,u>需要被区分.

所谓模式串的重复,是将若干个模式串S依次相接(不能重叠).例如当S=PLUS的时候,重复两次会得到PLUSPLUS,

重复三次会得到PLUSPLUSPLUS,同时要注恿,重复必须是整数次的。例如当S=XYXY时,因为必须重复整数次,所以X

YXYXY不能看作是S重复若干次得到的。

输入格式

每一个数据有多组测试,

第一行输入一个整数C,表示总的测试个数。

对于每一组测试来说:

第一行输入两个整数,分别表示树T的结点个数n与模式长度m。结点被依次编号为1到n,

之后一行,依次给出了n个大写字母(以一个长度为n的字符串的形式给出),依次对应树上每一个结点上的字符(

第i个字符对应了第i个结点).

之后n-1行,每行有两个整数u和v表示树上的一条无向边,之后一行给定一个长度为m的由大写字母组成的字符串,

为模式串S。

1<=C<=10,3<=N<=10000003<=M<=1000000

输出格式

给出C行,对应C组测试。每一行输出一个整数,表示有多少对节点<u,v>满足从u到v的路径形成的字符串恰好是模

式串的若干次重复.

输入样例

1

11 4

IODSSDSOIOI

1 2

2 3

3 4

1 5

5 6

6 7

3 8

8 9

6 10

10 11

SDOI

输出样例

5

提示

数据文件太过巨大,仅提供前三组数据测试.

题解

BZOJ数据较小,卡过了

但洛谷似乎T得不行

我们预处理出字符串前i个和后i个的hash值【这里\(i<=n\)处理的字符串由原字符串复制多次形成】

然后点分

对于每棵子树,进行遍历,记录当前到根的hash值,如果匹配上了前缀或者后缀,查找f[i]或者g[i]表示长度对m取模后为i的到根路径为原字符串前缀或后缀的路径数,更新答案

常熟略大,,弱弱卡过

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #define LL long long int
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define ULL unsigned long long int
  10. #define cls(s) memset(s,0,sizeof(s))
  11. #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
  12. using namespace std;
  13. const int maxn = 1000005,maxm = 2000005,INF = 1000000000;
  14. inline int read(){
  15. int out = 0,flag = 1; char c = getchar();
  16. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  17. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  18. return out * flag;
  19. }
  20. ULL Hl[maxn],Hr[maxn];
  21. char s[maxn],val[maxn];
  22. int n,m;
  23. int h[maxn],ne = 2;
  24. int F[maxn],Siz[maxn],fa[maxn],vis[maxn],sum,rt;
  25. LL ans;
  26. struct EDGE{int to,nxt;}ed[maxm];
  27. void build(int u,int v){
  28. ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
  29. ed[ne] = (EDGE){u,h[v]}; h[v] = ne++;
  30. }
  31. void init(){
  32. for (int i = 1; i <= n; i++) vis[i] = h[i] = fa[i] = 0;
  33. ne = 2; ans = 0;
  34. }
  35. void getrt(int u){
  36. Siz[u] = 1; F[u] = 0;
  37. Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
  38. fa[to] = u; getrt(to);
  39. Siz[u] += Siz[to];
  40. F[u] = max(F[u],Siz[to]);
  41. }
  42. F[u] = max(F[u],sum - Siz[u]);
  43. if (F[u] < F[rt]) rt = u;
  44. }
  45. int pre[maxn],post[maxn],dep[maxn];
  46. ULL V[maxn],P[maxn];
  47. void DFS(int u){
  48. Siz[u] = 1;
  49. Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
  50. fa[to] = u; DFS(to);
  51. Siz[u] += Siz[to];
  52. }
  53. }
  54. void dfs1(int u){
  55. V[u] = V[fa[u]] * 107 + val[u];
  56. int d = (dep[u] - 1) % m + 1;
  57. if (V[u] == Hl[dep[u]] && s[d % m + 1] == val[rt]){
  58. //printf("find at %d\n",u);
  59. ans += post[((m - d - 1) % m + m) % m];
  60. }
  61. if (V[u] == Hr[dep[u]] && s[m - d % m] == val[rt]){
  62. //printf("rfind at %d\n",u);
  63. ans += pre[((m - d - 1) % m + m) % m];
  64. }
  65. Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
  66. fa[to] = u; dep[to] = dep[u] + 1;
  67. dfs1(to);
  68. }
  69. }
  70. void dfs2(int u){
  71. int d = dep[u] % m;
  72. if (V[u] == Hr[dep[u]]) post[d]++;
  73. if (V[u] == Hl[dep[u]]) pre[d]++;
  74. Redge(u) if (!vis[to = ed[k].to] && to != fa[u]){
  75. fa[to] = u; dep[to] = dep[u] + 1;
  76. dfs2(to);
  77. }
  78. }
  79. void solve(int u){
  80. vis[u] = true;
  81. fa[u] = 0; DFS(u);
  82. if (Siz[u] < m) return;
  83. for (int i = min(Siz[u],m); i >= 0; i--) pre[i] = post[i] = 0;
  84. pre[0] = post[0] = 1;
  85. V[u] = 0;
  86. Redge(u) if (!vis[to = ed[k].to]){
  87. dep[to] = 1; fa[to] = u; dfs1(to);
  88. dep[to] = 1; fa[to] = u; dfs2(to);
  89. }
  90. Redge(u) if (!vis[to = ed[k].to]){
  91. sum = Siz[to]; F[rt = 0] = INF;
  92. getrt(to); solve(rt);
  93. }
  94. }
  95. int main(){
  96. P[0] = 1;
  97. for (int i = 1; i <= 1000000; i++) P[i] = P[i - 1] * 107;
  98. int T = read();
  99. while (T--){
  100. init();
  101. n = read(); m = read();
  102. scanf("%s",s + 1);
  103. for (int i = 1; i <= n; i++) val[i] = s[i];
  104. for (int i = 1; i < n; i++) build(read(),read());
  105. scanf("%s",s + 1);
  106. for (int i = 1; i <= n; i++)
  107. Hl[i] = Hl[i - 1] + P[i - 1] * s[(i - 1) % m + 1];
  108. for (int i = 1; i <= n; i++)
  109. Hr[i] = Hr[i - 1] + P[i - 1] * s[m - (i - 1) % m];
  110. F[rt = 0] = INF; sum = n;
  111. getrt(1); solve(rt);
  112. printf("%lld\n",ans);
  113. }
  114. return 0;
  115. }

BZOJ4598 [Sdoi2016]模式字符串 【点分治 + hash】的更多相关文章

  1. BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)

    题意 题目链接 Sol 直接考虑点分治+hash匹配 设\(up[i]\)表示\(dep \% M = i\)的从下往上恰好与前\(i\)位匹配的个数 \(down\)表示\(dep \% M = i ...

  2. 【BZOJ4598】[Sdoi2016]模式字符串 树分治+hash

    [BZOJ4598][Sdoi2016]模式字符串 Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每 ...

  3. BZOJ.4598.[SDOI2016]模式字符串(点分治 Hash)

    LOJ BZOJ 洛谷 点分治.考虑如何计算过\(rt\)的答案. 记\(pre[i]\)表示(之前的)子树内循环匹配了\(S\)的前缀\(i\)的路径有多少,\(suf[i]\)表示(之前的)子树内 ...

  4. Bzoj4598: [Sdoi2016]模式字符串 点分治 哈希

    国际惯例的题面:这种关于树上路径的题,我也没什么好办法,只好点分治.考虑当前分治重心为root,如何统计经过分治重心的路径的答案.我们令prf[i]表示某个点到root的路径(不含root)已经循环匹 ...

  5. bzoj4598: [Sdoi2016]模式字符串

    Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m 的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有 ...

  6. P4075 [SDOI2016]模式字符串

    总结 P4075 [SDOI2016]模式字符串 题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z ...

  7. [SDOI2016] 模式字符串 (BZOJ4598 & VIJOS1995)

    首先直接点分+hash就可以做,每个点用hash判断是否为S重复若干次后的前缀或后缀,每个子树与之前的结果O(m)暴力合并.在子树大小<m时停止分治,则总复杂度为O(nlog(n/m)). 问题 ...

  8. bzoj 4598: [Sdoi2016]模式字符串

    题目描述 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母. Alice希望知道,有多少对结点&l ...

  9. [SDOI2016]模式字符串

    Description 给出n个结点的树结构T,其中每一个结点上有一个字符,这里我们所说的字符只考虑大写字母A到Z,再给出长度为m的模式串s,其中每一位仍然是A到z的大写字母.Alice希望知道,有多 ...

随机推荐

  1. [dp]uestc oj E - 菲波拉契数制

    E - 菲波拉契数制 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  2. codeforce Gym 100570B ShortestPath Query (最短路SPFA)

    题意:询问单源最短路径,每条边有一个颜色,要求路径上相邻边的颜色不能相同,无重边且边权为正. 题解:因为路径的合法性和边的颜色有关, 所以在做spfa的时候,把边丢到队列中去,松弛的时候注意判断一下颜 ...

  3. 2018.2.28 PHP中使用jQuery+Ajax实现分页查询多功能如何操作

    PHP中使用jQuery+Ajax实现分页查询多功能如何操作 1.首先做主页Ajax_pag.php 代码如下 <!DOCTYPE html> <html> <head& ...

  4. DROP GROUP - 删除一个用户组

    SYNOPSIS DROP GROUP name DESCRIPTION 描述 DROP GROUP 从数据库中删除指定的组.组中的用户不被删除. 组中的用户不被删除. PARAMETERS 参数 n ...

  5. iframe的document操作

    导语: 在我写网页代填插件的时候,有遇到拿不到input元素的时候,这时候我去看元素布局,发现有些网站登录那一块是用iframe标签写的,这时候我需要取到的那就是iframe标签下input元素 1. ...

  6. JTT808、JTT809、JTT796、JTT794、JTT1077、JTT1078区别与交通部道路运输车辆卫星定位系统部标标准大全下载地址

    部标JT/T808协议.JT/T809协议.JT/T796标准.JT/T794标准的区别,他们是基于不同的通信场景,不同的通信对象,不同的设计目的和目标而制定出来的.首先要知道这些标准的全称是什么意思 ...

  7. 代码块(block)的使用

    Objective-C语法之代码块(block)的使用 代码块本质上是和其他变量类似.不同的是,代码块存储的数据是一个函数体.使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值. 脱 ...

  8. iOS开发之蓝牙业务封装

    因为公司做智能家居开发,有很多蓝牙的智能硬件.因此项目中经常需要和蓝牙打交道.为此为了提高开发效率,就把蓝牙的公共业务进行了封装. 本文将对封装的思路做一个简单的阐述. 首先我们需要一个头文件.在这个 ...

  9. css3中的nth-child和nth-of-type的区别

    实例: 首先创建一个HTML结构 <div class="post"> <p>我是文章的第一段落</p> <p>我是文章的第二段落& ...

  10. C语言程序运行

    vs2013编辑器 c程序的运行   一.启动Microsoft Visual C++  2013版.新建项目 . 1.  文件——> 新建——> 项目.       2. 确定之后 弹出 ...