1 一、后缀数组 2 #define maxn 200015 3 int wa[maxn],wb[maxn],wv[maxn],WS[maxn]; 4 int len, sa[maxn] ; 5 inline void swap(int &x, int &y) { int t = x ; x = y ; y = t ; } 6 inline int min(int x, int y) {return x < y ? x : y ; } 7 inline int max(int x, int y) {return x > y ? x : y ; } 8 inline int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];} 9 void da(int *r,int *sa,int n,int m){ 10 int i,j,p,*x=wa,*y=wb,*t; 11 for(i=0;i<m;i++) WS[i]=0; 12 for(i=0;i<n;i++) WS[x[i]=r[i]]++; 13 for(i=1;i<m;i++) WS[i]+=WS[i-1]; 14 for(i=n-1;i>=0;i--) sa[--WS[x[i]]]=i; 15 for(j=1,p=1;p<n;j*=2,m=p) 16 { 17 for(p=0,i=n-j;i<n;i++) y[p++]=i; 18 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 19 for(i=0;i<n;i++) wv[i]=x[y[i]]; 20 for(i=0;i<m;i++) WS[i]=0; 21 for(i=0;i<n;i++) WS[wv[i]]++; 22 for(i=1;i<m;i++) WS[i]+=WS[i-1]; 23 for(i=n-1;i>=0;i--) sa[--WS[wv[i]]]=y[i]; 24 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 25 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 26 } 27 return; 28 } 29 int Rank[maxn], height[maxn]; 30 int s[maxn] ; 31 void calheight(int *r,int *sa,int n){ 32 int i,j,k=0; 33 for(i=1;i<=n;i++) Rank[sa[i]]=i; 34 for(i=0;i<n;height[Rank[i++]]=k) 35 for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++); 36 }int lsa[maxn], tmp[maxn] ; 37 void init_SA(){ 38 int i, t ; 39 for(len = 0 ; A[len] ; len ++) s[len] = static_cast<int>(A[len]) ; 40 s[len] = 0 ; 41 da(s, sa, len+1, 259) ; 42 calheight(s, sa, len) ; 43 } 44 45 二、KMP & Manancher 46 1.模板 47 void getNext() { 48 int j = 0 , k = -1 ; 49 next[0] = -1 ; 50 while(j < tl ) // next[i] = max {j | t[i, j] == t[i+1 - j, i] } ; 51 { 52 if(k == -1 || t[j] == t[k] ) next[ ++j] = ++ k ; 53 else k = next[k] ; 54 } 55 } 56 int kmp_Index(){ 57 int l = -1, r = sl ; 58 int i = 0 , j = 0 ; 59 while(i < sl && j < tl ) 60 { 61 if(j == -1 || s[i] == t[j] ) 62 { 63 if(!j ) l = i ; 64 else if(j == tl-1) r = i ; 65 i ++ ; j ++ ; 66 } 67 else j = next[j] ; 68 } 69 printf("%d %d ", l, r ) ; 70 if(j == tl ) return i - tl ; 71 else return -1 ; 72 } 73 int kmp_Count(){ 74 int ans = 0 ; 75 int i, j ; 76 if(sl == 1 && tl == 1) 77 { 78 if(s[0] == t[0] ) return 1 ; 79 else return 0 ; 80 } 81 for(i = 0, j = 0 ; i < sl ; i ++ ) 82 { 83 while(j > 0 && s[i] != t[j] ) j = next[j] ; 84 if(s[i] == t[j] ) j ++ ; 85 if(j == tl ) 86 { 87 ans ++ ; 88 j = next[j] ; // 提前更新,防治t数组越界 ; 89 } 90 } 91 return ans ; 92 } 93 2.字符串周期 94 int solve(){ 95 for(i = 1 ; i <= n ; i ++ ){ 96 len = i - next[i] ; 97 if(next[i] && !(i % len ) ) printf("%d %d ", i , i / len ) ; // 98 } 99 } 100 3.T与S[i,n]的最长公共前缀 101 //extend[i] 数组表示T 与 S[i , n -1] 的最长公共前缀 ; 102 void build_Next(){ 103 int k, q, p, a ; 104 next[0] = n ; 105 for (k = 1 , q = -1 ; k < n ; k ++, q --) 106 { 107 if (q < 0 || k + next[k - a] >= p) 108 { 109 if (q < 0 ) q = 0 , p = k ; 110 //q是B串继续向后匹配的指针,p是A串继续向后匹配的指针, 111 也是曾经到达过的最远位置+1 112 //q在每次计算后会减小1,直观的讲就是B串向后错了一位 113 while (p < n && t[p] == t[q]) p ++, q ++ ; 114 next[k] = q, a = k ; 115 } 116 else next[k] = next[k - a] ; 117 } 118 } 119 void extend_KMP(){ 120 int k, q, p, a; 121 for (k = 0, q = -1; k < n ; k ++, q --) 122 { 123 if (q < 0 || k + next[k - a] >= p) 124 { 125 if (q < 0) q = 0, p = k ; 126 while (p < n && q < n && s[p] == t[q]) 127 { 128 p ++ ; 129 q ++ ; 130 } 131 extend[k] = q ; 132 a = k ; 133 } 134 else extend[k] = next[k - a]; 135 } 136 } 137 /*void ExtendKmp(char ss[],int ls,char tt[],int lt){// 直接调用; 138 int i,j,k; 139 int Len,L; 140 j=0; 141 while(tt[j+1]==tt[j]&&j+1<lt) j++; 142 next[1]=j,k=1; 143 for(i=2;i<lt;i++){ 144 Len=k+next[k],L=next[i-k]; 145 if(Len>L+i) next[i]=L; 146 else{ 147 j=Len-i>0?Len-i:0; 148 while(tt[i+j]==tt[j]&&i+j<lt) j++; 149 next[i]=j,k=i; 150 } 151 } 152 j=0; 153 while(ss[j]==tt[j]&&j<lt&&j<ls) j++; 154 extend[0]=j,k=0; 155 for(i=1;i<ls;i++){ 156 Len=k+extend[k],L=next[i-k]; 157 if(Len>L+i) extend[i]=L; 158 else{ 159 j=Len-i>0?Len-i:0; 160 while(ss[i+j]==tt[j]&&i+j<ls&&j<lt) j++; 161 extend[i]=j,k=i; 162 } 163 } 164 } */ 165 4.Manancger算法 166 void initStr(){ // 将原字符串a 转化为加了'#'号的字符串 s, 167 // 将问题全转化为“长度都为奇数”的情况; 168 int i , n = strlen(a) ; 169 for(i = 1 ; i <= n ; i ++ ) 170 { 171 s[2*i] = a[i-1] ; 172 s[2*i + 1 ] = '#' ; 173 } 174 s[2*i] = '