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 if(rk[i]==1) continue;
66 comp = sa[rk[i]-1]; 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 if(L == R) return n-sa[L]; if(L > R) swap(L,R); 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 }