hdu 3948
1 /* 2 题意:给你一个串,求该串的不同子回文串的个数; 3 4 分析:首先我们想一下一个比较简单的问,求一个串的不同子串的个数 5 显然每个子串都是一个后缀的前缀,那么只要按照SA[]统计该后缀i的前缀 6 有那些是出现过的,也就是ans+=len[该后缀长]-height[i]; 7 8 9 同样的道理,我们先统计出以i为中心的回文串到最右边的距离,然后 10 再统计不同回文串的个数,即减去相同回文串的个数,但是两者还是有区别的 11 其次,为了统一奇偶的差别,我们构造出另一个字符串, 12 s1=aabaa -> s=$#a#a#b#a#a# (可以参看本博客前前篇文章MANACHER) 13 首先我用MANACHER的预处理出以s[i]为中心的回文串到最右边的距离记录在lc[i]; 14 当然可以直接用后缀数组的方法求出(将反串加在原串后面,然后询问后缀i和后缀2*n-i的LCP,但要分奇偶) 15 16 统计不同子串个数和统计不同回文串的个数的区别 17 看样例:aabaa 18 19 20 构造的串:$#a#a#b#a#a# 21 后缀 lc[i] 回文串的个数 22 11 1 # 1 23 9 3 #a# 3 24 7 1 #a#a# 1 25 1 1 #a#a#b#a#a# 1 26 3 3 #a#b#a#a# 3 & 27 5 1 #b#a#a# 1 28 29 0 1 $#a#a#b#a#a# 1 30 10 2 a# 2 31 8 2 a#a# 2 32 2 2 a#a#b#a#a# 2 33 4 2 a#b#a#a# 2 34 6 6 b#a#a# 6 35 36 先不考虑加入#后产生的回文串, 37 在统计后缀3中包含的回文串时,会把#a,和#a#统计进去,但我们发现在统计后缀9时#a,#a#就已经被统计了 38 也就是说统计后缀i中已经被统计过的回文串的个数,不一定只是后缀i-1中的回文,还有可能是更前面的, 39 所以我们在遍历的过程中设置一个标记tmp,表示以字符i为中点能延伸的最长距离,而不是该串在原串中能延伸的距离 40 41 至于加入#后多出了的回文串,可以发现不管是lc[]还是height[]长度都是延伸到#位置的也就是相减后/2就是原串的个数 42 还有加进了#最后答案要减去1; 43 44 */ 45 #include<cstdio> 46 #include<cstring> 47 #include<cstdlib> 48 #include<iostream> 49 #include<algorithm> 50 #include<cmath> 51 #include<vector> 52 using namespace std; 53 typedef long long LL; 54 const int N=200000+10; 55 char s[N],s1[N]; 56 struct SuffixArray{ 57 int a1[N],a2[N],c[N],SA[N],sa[N],*rank,*x,*y; 58 int n,height[N],m; 59 void sort(){ 60 for (int i=0;i<m;i++) c[i]=0; 61 for (int i=0;i<n;i++) c[x[i]]++; 62 for (int i=0;i<m;i++) c[i+1]+=c[i]; 63 for (int i=n-1;i>=0;i--) SA[ --c[x[sa[i]]] ] = sa[i]; 64 } 65 void build_sa(char *s){ 66 n=strlen(s); m=256; 67 x=a1; y=a2; x[n]=y[n]=-1; 68 for (int i=0;i<n;i++) x[i]=s[i],sa[i]=i; 69 sort(); 70 for (int k=1;k<=n;k<<=1){ 71 int p=0; 72 for (int i=n-k;i<n;i++) sa[p++]=i; 73 for (int i=0;i<n;i++) if (SA[i]>=k) sa[p++]=SA[i]-k; 74 sort(); 75 p=0; swap(x,y); 76 x[SA[0]]=0; 77 for (int i=1;i<n;i++){ 78 if ( y[ SA[i-1] ]!=y[ SA[i] ] || y[ SA[i-1]+k ]!=y[ SA[i]+k ] ) p++; 79 x[SA[i]]=p; 80 } 81 if (p+1==n) break; 82 m=p+1; 83 } 84 rank=x; getHeight(s); 85 } 86 void getHeight(char *s){ 87 int k=0; 88 for (int i=0;i<n;i++){ 89 if (k) k--; 90 if (rank[i]==0) continue; 91 int j=SA[ rank[i]-1 ]; 92 while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++; 93 height[rank[i]]=k; 94 } 95 height[n]=0; 96 } 97 }H; 98 int lc[N*2]; 99 int lx[N],ly[N]; 100 void init(char *s1){ 101 int c=0; 102 int n=strlen(s1); 103 s[c++]='$';s[c++]='#'; 104 for (int i=0;s1[i];i++){ 105 s[c++]=s1[i]; 106 s[c++]='#'; 107 }s[c]='