zoukankan      html  css  js  c++  java
  • BZOJ 3676: [Apio2014]回文串 后缀自动机 Manacher 倍增

    http://www.lydsy.com/JudgeOnline/problem.php?id=3676

    过程很艰难了,第一次提交Manacher忘了更新p数组,超时,第二次是倍增的第0维直接在自动机里完成,但是忽略了增加新点时fa变动的情况,还是肉眼查错最管用。

    得到的教训是既然倍增就在倍增的函数里完成,自动机就在自动机里完成,不要随便乱搞赋值。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<map>
     7 using namespace std;
     8 const int maxn=300010;
     9 char ch[maxn]={};
    10 char ch1[maxn*2]={};
    11 int siz,siz1;
    12 struct sam{
    13     int sig[26];
    14     int f,len,d[21],num;
    15 }t[maxn*2];
    16 int tot=1,la=1;
    17 int loc[maxn]={},cnt[maxn*2]={},b[maxn*2]={},p[maxn*2]={};
    18 long long ans=0;
    19 void add(int z){
    20     int x=++tot,i=la;
    21     t[x].len=t[la].len+1;
    22     for(;i&&!t[i].sig[z];i=t[i].f)
    23         t[i].sig[z]=x;
    24     if(!i)t[x].f=1;
    25     else{
    26         int p=t[i].sig[z];
    27         if(t[p].len==t[i].len+1)t[x].f=p;
    28         else{
    29             int y=++tot;
    30             t[y]=t[p];t[y].len=t[i].len+1;
    31             t[p].f=t[x].f=y;
    32             for(;i&&t[i].sig[z]==p;i=t[i].f)
    33                 t[i].sig[z]=y;
    34         }
    35     }
    36     la=x;
    37 }
    38 void pre(){
    39     int z;
    40     for(int i=1;i<=tot;i++)cnt[t[i].len]++;
    41     for(int i=1;i<=siz;i++)cnt[i]+=cnt[i-1];
    42     for(int i=tot;i;i--)b[cnt[t[i].len]--]=i;
    43     for(int i=1;i<=siz;i++)t[loc[i]].num=1;
    44     for(int i=tot;i;i--){
    45         z=b[i];t[t[z].f].num+=t[z].num;
    46     }
    47     for(int i=1;i<=tot;i++){
    48         z=b[i];t[z].d[0]=t[z].f;
    49         for(int j=1;j<=20;j++)
    50             t[z].d[j]=t[t[z].d[j-1]].d[j-1];
    51     }
    52 }
    53 void getit(int l,int r){
    54     r=r/2;l=(l+1)/2;
    55     if(r<l)return;
    56     int z=loc[r];
    57     for(int i=20;i>-1;i--){
    58         if(t[t[z].d[i]].len>=r-l+1){
    59             z=t[z].d[i];        
    60         }
    61     }
    62     long long sum=(long long)t[z].num*(r-l+1);
    63     if(ans<sum)ans=sum;
    64 }
    65 void Manacher(){
    66     for(int i=1;i<=siz;i++)ch1[i*2]=ch[i],ch1[i*2-1]='#';
    67     ch1[siz*2+1]='#';ch1[siz*2+2]='';ch1[0]='$';
    68     siz1=siz*2+1;
    69     int mx=0,id=0;
    70     for(int i=1;i<=siz1;i++){
    71         if(mx>=i)p[i]=min(mx-i,p[id*2-i]);
    72         else p[i]=0;
    73         while(ch1[i+p[i]]==ch1[i-p[i]]){++p[i];getit(i-p[i]+1,i+p[i]-1);}
    74         if(mx<i+p[i]){mx=i+p[i];id=i;}
    75     }
    76 }
    77 int main(){
    78     memset(t,0,sizeof(t));
    79     scanf("%s",ch+1);siz=strlen(ch+1);
    80     for(int i=1;i<=siz;i++){loc[i]=tot+1;add(ch[i]-'a');}
    81     pre();
    82     Manacher();
    83     printf("%lld
    ",ans);
    84     return 0;
    85 }
    View Code

  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number (考虑负数的情况)
    8. String to Integer (整数的溢出)
    7. Reverse Integer (整数的溢出)
    LeetCode Minimum Size Subarray Sum
    LeetCode Course Schedule II
    Linux 文件缓存 (一)
    LeetCode Tries Prefix Tree
    Linux : lsof 命令
    LeetCode Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8572781.html
Copyright © 2011-2022 走看看