• 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

  • 相关阅读:
    Android Activity 四种启动模式
    Android Activity的生命周期
    Android SQLite (五 ) 全面详解(三)
    Android SQLite (四 ) 全面详解(二)
    工作流设计 zt
    法律网站分类 ­zt
    刑事案件的构成要素 zt
    犯罪构成三层次记忆口诀 zt
    E asy Boo t 6.51 启动易 制作启动光盘的软件(附注册码)
    父线程开启子进程且共享内存
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8572781.html
Copyright © 2020-2023  润新知