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 }

 

posted @ 2018-09-04 12:43  menhera  阅读(221)  评论(0编辑  收藏  举报