[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 }
原文地址:https://www.cnblogs.com/Gster/p/5090517.html