BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】

题目分析:

我写了史上最丑的后缀数组,怎么办?

首先manacher一遍两个串,这样只用考虑第三问。用$作为间隔符拼接两个串,把第一个串翻转。枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配即可。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define Sec first.second
  5 #define Fir first.first
  6 
  7 const int maxn = 201000;
  8 
  9 int n,as,f[maxn],sa[maxn],height[maxn],h[maxn],rk[maxn*2];
 10 string s1,s2,vk;
 11 int RMQ[maxn][19];
 12 
 13 void read(){cin >> n; cin >> s1 >> s2;}
 14 int pf[maxn][2];
 15 
 16 void manacher(string &str){
 17     vk.clear();
 18     memset(f,0,sizeof(f));
 19     for(int i=0;i<n;i++) vk.push_back(str[i]),vk.push_back('$');
 20     f[0] = 1; int last = 1,ct = 0;
 21     for(int i=1;i<2*n;i++){
 22     f[i] = 1;
 23     if(i <= ct+last-1 && i+f[2*ct-i]-1 <= ct+last-1) f[i]=f[2*ct-i];
 24     while(i-f[i]>=0&&i+f[i]<2*n&&vk[i-f[i]]==vk[i+f[i]]){f[i]++;}
 25     if(ct+last-1 < i+f[i]-1) ct = i,last = f[i];
 26     }
 27 }
 28 int X[maxn];
 29 pair<pair<int,int>,int> pr[maxn];
 30 vector <pair<int,int> > vec[maxn];
 31 void get_sa(){
 32     int z = s1.length();
 33     for(int i=0;i<z;i++) X[s1[i]]++;
 34     for(int i=1;i<=95;i++)X[i] += X[i-1];
 35     for(int i=0;i<z;i++) rk[i] = X[s1[i]];
 36     for(int k=1;(1<<k)<=z;k++){
 37     for(int i=0;i<z;i++)
 38         vec[rk[i+(1<<k-1)]].push_back(make_pair(rk[i],i));
 39     //pr[i+1]=make_pair(make_pair(rk[i],rk[i+(1<<k-1)]),i);
 40     //sort(pr+1,pr+z+1);
 41     for(int i=0,tms=0;i<=z;i++)
 42         for(int j=vec[i].size()-1;j>=0;j--){
 43         pr[++tms]=make_pair(make_pair(vec[i][j].first,i),vec[i][j].second);
 44         vec[i].pop_back();
 45         }
 46     for(int i=z;i>=1;i--)
 47         vec[pr[i].Fir].push_back(make_pair(pr[i].Sec,pr[i].second));
 48     for(int i=0,tms=0;i<=z;i++)
 49         for(int j=vec[i].size()-1;j>=0;j--){
 50         pr[++tms] = make_pair(make_pair(i,vec[i][j].first),vec[i][j].second);
 51         vec[i].pop_back();
 52         }
 53     int num = 0;
 54     for(int i=1;i<=z;i++){
 55         if(pr[i].first == pr[i-1].first) rk[pr[i].second]=num;
 56         else num++,rk[pr[i].second] = num;
 57     }
 58     }
 59     for(int i=0;i<z;i++) sa[rk[i]] = i;
 60 }
 61 void get_height(){
 62     int z = s1.length();
 63     for(int i=0;i<z;i++){
 64     if(i) h[i] = max(0,h[i-1]-1); else h[i] = 0;
 65     int comp = sa[rk[i]-1];
 66     if(comp == 0) continue;
 67     while(s1[comp+h[i]] == s1[i+h[i]])h[i]++;
 68     }
 69     for(int i=0;i<z;i++) height[rk[i]] = h[i];
 70     for(int i=1;i<=z;i++) RMQ[i][0] = height[i];
 71     for(int k=1;(1<<k)<=z;k++){
 72     for(int i=1;i<=z;i++){
 73         if(i+(1<<k-1)>z) RMQ[i][k] = RMQ[i][k-1];
 74         else RMQ[i][k] = min(RMQ[i][k-1],RMQ[i+(1<<k-1)][k-1]);
 75     }
 76     }
 77 }
 78 int getLCP(int L,int R){
 79     L++;
 80     int k = 0; while((1<<k+1)<=R-L+1)k++;
 81     return min(RMQ[L][k],RMQ[R-(1<<k)+1][k]);
 82 }
 83 
 84 void work(){
 85     manacher(s1);
 86     for(int i=0;i<2*n;i++) pf[i][0] = f[i];
 87     manacher(s2);
 88     for(int i=0;i<2*n;i++) pf[i][1] = f[i];
 89     for(int i=0;i<n/2;i++) swap(s1[i],s1[s1.length()-i-1]);
 90     s1.push_back('$');
 91     for(int i=0;i<n;i++) s1.push_back(s2[i]);
 92     get_sa(); get_height();
 93     for(int i=0;i<2*n;i+=2) {
 94     if(pf[i][0]%2==0)pf[i][0]--;
 95     int z = (i-pf[i][0]+1)/2,w = (i+pf[i][0]-1)/2;
 96     int L = rk[n-z],R = rk[n+w+1];
 97     if(L > R) swap(L,R); int len = getLCP(L,R); as=max(as,w-z+1+len*2);
 98     if(pf[i][1]%2==0)pf[i][1]--;
 99     z = (i-pf[i][1]+1)/2,w = (i+pf[i][1]-1)/2;
100     L = rk[n-z-1],R = rk[n+w+2];
101     if(L > R) swap(L,R); len = getLCP(L,R); as = max(as,w-z+1+len*2);
102     }
103     for(int i=1;i<2*n;i+=2) {
104     if(pf[i][0]&1) pf[i][0]--;
105     int z = i-pf[i][0]+1,w = i+pf[i][0]-1;
106     if(pf[i][0] == 0){
107         int L = rk[n-(i-1)/2-1],R = rk[n+1+(i-1)/2];
108         if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,len*2);
109     } else{
110         z/=2,w/=2; int L = rk[n-z],R = rk[n+1+w];
111         if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,w-z+1+len*2);
112     }
113     if(pf[i][1]&1) pf[i][1]--;
114     z = i-pf[i][1]+1,w = i+pf[i][1]-1;
115     if(pf[i][1] == 0){
116         int L = rk[n-(i-1)/2-1],R = rk[n+1+(i-1)/2];
117         if(L>R) swap(L,R); int len = getLCP(L,R); as = max(as,len*2);
118     }else{
119         z/=2,w/=2; int L = rk[n-z-1],R = rk[n+w+2];
120         if(L > R) swap(L,R);int len=getLCP(L,R);as=max(as,w-z+1+len*2);
121         
122     }
123     }
124     printf("%d",as);
125 }
126 
127 int main(){
128     //freopen("2.in","r",stdin);
129     read();
130     work();
131     return 0;
132 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/9583732.html