• 解题:APIO 2014 回文串


    题面

    初见SAM

    洛谷数据太弱了,我SAM写错了居然有90pts=。=???

    SAM求一个子串$(l,r)$的出现次数:从右端点对应状态开始在parent树上倍增,当目标节点的$len$大于等于子串长度时就往上跳,最后所在节点的$len$就是该串的出现次数

    于是边$manacher$边在SAM上统计当前串的出现次数即可,复杂度$O(nlog n)$,注意边界

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=600060,K=20;
     6 int p[N],noww[N],goal[N];
     7 int rnk[N],bkt[N],mul[N][K];
     8 int trs[N][26],fth[N],len[N],siz[N],num[N];
     9 char str[N>>1],Str[N]; 
    10 int lth,lst,cnt,tot,mid,maxr;
    11 long long ans;
    12 void link(int f,int t)
    13 {
    14     noww[++cnt]=p[f];
    15     goal[cnt]=t,p[f]=cnt;
    16 }
    17 void DFS(int nde,int fth)
    18 {
    19     mul[nde][0]=fth;
    20     for(int i=p[nde];i;i=noww[i]) 
    21         DFS(goal[i],nde),siz[nde]+=siz[goal[i]];
    22     for(int i=1;mul[nde][i];i++)
    23         mul[nde][i]=mul[mul[nde][i-1]][i-1];
    24 }
    25 void Insert(int ch,int ps)
    26 {
    27     int nde=lst,newn=++tot; 
    28     num[ps]=lst=newn,siz[newn]=1,len[newn]=len[nde]+1;
    29     while(nde&&!trs[nde][ch])
    30         trs[nde][ch]=newn,nde=fth[nde];
    31     if(!nde) fth[newn]=1;
    32     else
    33     {
    34         int tran=trs[nde][ch];
    35         if(len[tran]==len[nde]+1)
    36             fth[newn]=tran;
    37         else
    38         {
    39             int rnde=++tot; len[rnde]=len[nde]+1;
    40             for(int i=0;i<=25;i++) trs[rnde][i]=trs[tran][i];
    41             fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
    42             while(nde&&trs[nde][ch]==tran)
    43                 trs[nde][ch]=rnde,nde=fth[nde];
    44         }
    45     }
    46 }
    47 void prework()
    48 {
    49     register int i,j;
    50     scanf("%s",str+1),lth=strlen(str+1),lst=tot=1;
    51     for(i=1;i<=lth;i++) Insert(str[i]-'a',i);
    52     for(i=1;i<=tot;i++) link(fth[i],i); DFS(1,0);
    53 }
    54 void Solve(int l,int r)
    55 {
    56     l=(l+l%2)/2,r=(r-r%2)/2; 
    57     if(l>r) return ;
    58     int nde=num[r],lth=r-l+1;
    59     for(int i=19;~i;i--)
    60         if(lth<=len[mul[nde][i]])
    61             nde=mul[nde][i];
    62     ans=max(ans,1ll*lth*siz[nde]);
    63 }
    64 void Manacher()
    65 {
    66     register int i;
    67     int newl=2*lth+1;
    68     for(i=1;i<=newl;i++)
    69         Str[i]=(i&1)?'?':str[i>>1];
    70     Str[0]='>',Str[newl+1]='<';
    71     for(i=1;i<=newl;i++)
    72     {
    73         fth[i]=(maxr>=i)?min(maxr-i+1,fth[2*mid-i]):1;
    74         Solve(i-fth[i]+1,i+fth[i]-1);
    75         while(Str[i-fth[i]]==Str[i+fth[i]]) 
    76             fth[i]++,Solve(i-fth[i]+1,i+fth[i]-1);
    77         if(i+fth[i]-1>maxr) maxr=i+fth[i]-1,mid=i;
    78     }
    79 }
    80 int main()
    81 {
    82     prework(),Manacher();
    83     printf("%lld",ans);
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    【LeetCode】96.Unique Binary Search Trees
    【LeetCode】136.Single Number
    VirtualBox下Linux加载Windows的共享目录
    Macbook上Windows的触摸板设置工具
    [转]太岁三煞五黄
    [转]UI、GUI、UE、UX、ID、UED、UCD的区别
    紫微斗数:命主和身主
    [转]如何降低二手烟的危害
    [转]从第六十三卦到第六十四卦
    Mac显示和隐藏隐藏文件
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10116400.html
Copyright © 2020-2023  润新知