后缀数组 hdu6661 Acesrc and String Theory

男娘i 2021-10-23 15:32 400阅读 0赞

Problem Description

Acesrc is a famous string theorist at Nanjing University second to none. He insists that we should always say an important thing k times. He also believes that every string that can be obtained by concatenating k copies of some nonempty string is splendid. So, he always teaches newcomers, ``String theory problems are important! String theory problems are important! … String theory problems are important!”

Today, he wants to examine whether the newcomers remember his instruction. He presents a string consisting of lower case letters and asks them the number of splendid substrings of the presented string. No one can solve this problem, and they will be scolded for hours. Can you help them solve this problem?

Note that equal splendid substrings occurred in different positions should be counted separately.

Input

The first line of input consists of a single integer T (1≤T≤10), denoting the number of test cases. Each test case starts with a single line of an integer k (1≤k≤20). The second line of a test case is a string S consisting of lower case letters only, the length of which is between 1 and 3×105 inclusive. The sum of the lengths of strings in all test cases never exceeds 106.

Outpu

For each test case, print the answer as a single integer in a single line.

Sample Input

3 2 aabb

2 abababab

3 abc

Sample Output

2

6

0

Source

2019 Multi-University Training Contest 8

这个题和poj3693一样,但是数据没有3693水,所以匹配前后缀以及在划分段的时候,要注意一下。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. const int M=1e6+50;
  6. int Log[M],K;
  7. long long res;
  8. struct Node{
  9. int n,m,rk[M],height[M],c[M],sa[M],x[M],y[M],t[M][35];
  10. char s[M];
  11. void getsa(){
  12. for(int i=0;i<=m;i++) c[i]=0;
  13. for (int i=1; i<=n; ++i) ++c[x[i]=s[i]-'a'+1];
  14. for (int i=2; i<=m; ++i) c[i]+=c[i-1];
  15. for (int i=n; i>=1; --i) sa[c[x[i]]--]=i;
  16. for (int k=1; k<=n; k<<=1) {
  17. int num=0;
  18. for (int i=n-k+1; i<=n; ++i) y[++num]=i;
  19. for (int i=1; i<=n; ++i) if (sa[i]>k) y[++num]=sa[i]-k;
  20. for (int i=1; i<=m; ++i) c[i]=0;
  21. for (int i=1; i<=n; ++i) ++c[x[i]];
  22. for (int i=2; i<=m; ++i) c[i]+=c[i-1];
  23. for (int i=n; i>=1; --i) sa[c[x[y[i]]]--]=y[i],y[i]=0;
  24. swap(x,y);
  25. x[sa[1]]=1;
  26. num=1;
  27. for (int i=2; i<=n; ++i)
  28. if((y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]))x[sa[i]]=num;
  29. else x[sa[i]]=++num;
  30. if (num==n) break;
  31. m=num;
  32. }
  33. int k=0;
  34. for (int i=1; i<=n; ++i) rk[sa[i]]=i;
  35. for (int i=1; i<=n; ++i) {
  36. if (rk[i]==1) continue;//第一名height为0
  37. if (k) --k;//h[i]>=h[i-1]-1;
  38. int j=sa[rk[i]-1];
  39. while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
  40. height[rk[i]]=k;
  41. }
  42. }
  43. void rmq(){
  44. for(int i=1;i<=n;i++)t[i][0]=height[i];
  45. for(int j=1;(1<<j)<=n;j++)
  46. for(int i=1;i+(1<<j)-1<=n;i++)
  47. t[i][j]=min(t[i][j-1],t[i+(1<<(j-1))][j-1]);
  48. }
  49. int ask(int l,int r){
  50. l=rk[l],r=rk[r];
  51. if(l>r)swap(l,r);
  52. l++;if(l>r)return 0;
  53. int tt=Log[r-l+1];
  54. return min(t[l][tt],t[r-(1<<tt)+1][tt]);
  55. }
  56. }A,B;
  57. void work(int l,int r,int j){
  58. int pre=B.ask(A.n-r+1,A.n-l+2),las=A.ask(l,r+1);
  59. l-=pre;r+=las;
  60. res+=max(0,r-l+1-K*j+1);
  61. }
  62. int main(){
  63. Log[1]=0;
  64. for(int i=2;i<M;i++)Log[i]=Log[i>>1]+1;
  65. int T;scanf("%d",&T);
  66. while(T--){
  67. scanf("%d",&K);
  68. scanf("%s",A.s+1);
  69. A.n=strlen(A.s+1);A.m=30;
  70. if(K==1){
  71. res=A.n;
  72. printf("%lld\n",res*(res+1)/2);
  73. continue;
  74. }else res=0;
  75. for(int i=1;i<=A.n;i++) B.s[A.n-i+1]=A.s[i];
  76. B.s[A.n+1]=0;
  77. B.n=A.n;
  78. B.m=A.m;
  79. A.getsa();B.getsa();
  80. A.rmq();B.rmq();
  81. // for(int i=1;i<=A.n;i++)cout<<A.sa[i]<<" ";cout<<endl;
  82. for(int j=1;j<=A.n/2;j++){
  83. int las=1;
  84. for(int i=j+1;i<=A.n;i+=j){
  85. if(A.ask(las,i)>=j)continue;
  86. work(las,i-1,j);
  87. if(i+j-1<=A.n)las=i;
  88. else las=0;
  89. }
  90. if(las)work(las,A.n,j);
  91. }
  92. printf("%lld\n",res);
  93. }
  94. return 0;
  95. }

发表评论

表情:
评论列表 (有 0 条评论,400人围观)

还没有评论,来说两句吧...

相关阅读

    相关 后缀数组

    转载自[后缀数组 学习笔记][Link 1] 后缀数组 最详细(maybe)讲解 后缀数组这个东西真的是神仙操作…… 但是这个比较神仙的东西在网上的讲解一般都仅限于思