zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    在asp.net实现文件下载
    Insus IO Utility
    Marquee无间隙滚动(二)
    Refactoring Parameter
    How do I filtered TextBox with a Decimal (double) Data Type
    创建自己的类库
    把选中Gridview的记录显示出来
    如何取得当前网页名称
    一位老程序员十年的职场感悟
    java 跳转语句
  • 原文地址:https://www.cnblogs.com/Menhera/p/9583732.html
Copyright © 2011-2022 走看看