[bzoj3676]回文串[后缀数组+Manacher]
后缀数组+Manacher
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <algorithm> 8 9 using namespace std; 10 11 long long Ans; 12 int A[310000],B[310000],U[310000]; 13 int SA[310000],*Rank,H[310000],Tmp[310000]; 14 int lg2[310000],ST[310000][20],p[610000]; 15 char str[610000]; 16 17 void Get_H(const int n) 18 { 19 int i,j,k=0; 20 for(i=0;i<n;H[Rank[i++]]=k) 21 for(k?k--:k,j=SA[Rank[i]-1];str[i+k]==str[j+k];++k); 22 for(i=2;i<=n;++i)lg2[i]=lg2[i>>1]+1; 23 for(i=1;i<=n;++i)ST[i][0]=H[i]; 24 for(j=1;(1<<j)<=n;++j) 25 { 26 for(i=1;i+(1<<j)-1<=n;++i) 27 { 28 ST[i][j]=min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]); 29 } 30 } 31 return ; 32 } 33 34 int Query(const int l,const int r) 35 { 36 int temp=lg2[r-l+1]; 37 return min(ST[l][temp],ST[r-(1<<temp)+1][temp]); 38 } 39 40 bool cmp(const int * s,const int a,const int b,const int l) 41 { 42 return s[a]==s[b] && s[a+l]==s[b+l]; 43 } 44 45 int* Get_SA(const int n,int m) 46 { 47 int i,j,_p,*x=A,*y=B; 48 for(i=0;i<m;++i)U[i]=0; 49 for(i=0;i<n;++i)U[x[i]=str[i]]++; 50 for(i=1;i<m;++i)U[i]+=U[i-1]; 51 for(i=n-1;i>=0;--i)SA[--U[x[i]]]=i; 52 53 for(j=1,_p=1;_p<n;m=_p,j<<=1) 54 { 55 for(_p=0,i=n-j;i<n;++i)y[_p++]=i; 56 for(i=0;i<n;++i)if(SA[i]>=j)y[_p++]=SA[i]-j; 57 for(i=0;i<n;++i)Tmp[i]=x[y[i]]; 58 for(i=0;i<m;++i)U[i]=0; 59 for(i=0;i<n;++i)U[Tmp[i]]++; 60 for(i=1;i<m;++i)U[i]+=U[i-1]; 61 for(i=n-1;i>=0;--i)SA[--U[Tmp[i]]]=y[i]; 62 for(swap(x,y),_p=1,x[SA[0]]=0,i=1;i<n;++i) 63 x[SA[i]]=cmp(y,SA[i-1],SA[i],j)?_p-1:_p++; 64 } 65 return x; 66 } 67 68 long long Calc(int l,int r,const int n) 69 { 70 l=(l-1)>>1,r=(r-2)>>1; 71 int pos=Rank[l],L,R,temp=1; 72 73 L=0,R=pos; 74 75 while(L<R-1) 76 { 77 int mid=L+((R-L)>>1); 78 if(Query(mid+1,pos)>=r-l+1)R=mid; 79 else L=mid; 80 } 81 82 temp+=pos-R; 83 L=pos,R=n+1; 84 85 while(L<R-1) 86 { 87 int mid=L+((R-L)>>1); 88 if(Query(pos+1,mid)>=r-l+1)L=mid; 89 else R=mid; 90 } 91 temp+=L-pos; 92 return (long long)temp*(r-l+1); 93 } 94 95 96 97 98 void Manacher(const int n) 99 { 100 int i,pos=0; 101 for(i=n-1;i>=0;--i) 102 { 103 str[i+i+2]=str[i]; 104 str[i+i+1]='#'; 105 } 106 str[0]='^';str[n<<1|1]='#';str[(n+1)<<1]='$'; 107 for(i=1;i<=(n<<1|1);++i) 108 { 109 if(p[pos]+pos>i) 110 p[i]=min(p[(pos<<1)-i],p[pos]+pos-i); 111 else p[i]=1; 112 while(str[i-p[i]]==str[i+p[i]]) 113 { if(i+p[i]>p[pos]+pos) Ans=max(Ans,Calc(i-p[i],i+p[i],n)); p[i]++; } 114 if(pos+p[pos]<i+p[i])pos=i; 115 } 116 117 return ; 118 } 119 120 121 int main() 122 { 123 int n; 124 125 scanf("%s",str); 126 127 n=strlen(str); 128 Rank=Get_SA(n+1,256); 129 Get_H(n); 130 Manacher(n); 131 132 printf("%lld",Ans); 133 134 return 0; 135 }