zoukankan      html  css  js  c++  java
  • [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)

    差分之后就是求多串LCS。

    对其中一个串建SAM,然后把其它串放在上面跑。

    对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值。答案就是res[]的最大值。

    考虑f[x]的求法,把s[]放在SAM上跑时,若下一个能正常匹配(即son[x][c]!=0)则直接len++,否则用经典的跳父亲,找到第一个son[k][c]!=0的点k,len=mx[k]+1,x=son[k][c]。
    每次更新最终匹配到的状态的f[]。同时注意到出现次数可以向父亲传递,于是Radixsort之后经典DP转移最长长度即可。

     1 #include<map>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 typedef long long ll;
     7 using namespace std;
     8 
     9 const int N=500010;
    10 int n,m,x,len,fir,lst=1,cnt=1,ans,res[N],s[N],f[N],mx[N],fa[N],c[N],q[N];
    11 map<int,int>son[N];
    12 
    13 void ext(int c){
    14     int p=lst,np=lst=++cnt; mx[np]=mx[p]+1;
    15     while (p && !son[p][c]) son[p][c]=np,p=fa[p];
    16     if (!p) fa[np]=1;
    17     else{
    18         int q=son[p][c];
    19         if (mx[q]==mx[p]+1) fa[np]=q;
    20         else{
    21             int nq=++cnt; mx[nq]=mx[p]+1; son[nq]=son[q];
    22             while (p && son[p][c]==q) son[p][c]=nq,p=fa[p];
    23             fa[nq]=fa[q]; fa[q]=fa[np]=nq;
    24         }
    25     }
    26 }
    27 
    28 void Radix(){
    29     rep(i,1,cnt) c[mx[i]]++;
    30     rep(i,1,cnt) c[i]+=c[i-1];
    31     for (int i=cnt; i; i--) q[c[mx[i]]--]=i;
    32     rep(i,1,cnt) res[i]=mx[i];
    33 }
    34 
    35 void Go(int s[],int n){
    36     int x=1,len=0;
    37     rep(i,1,n){
    38         int c=s[i];
    39         if (son[x][c]) x=son[x][c],f[x]=max(f[x],++len);
    40         else{
    41             while (x && !son[x][c]) x=fa[x];
    42             if (!x) x=1,len=0; else len=mx[x]+1,x=son[x][c],f[x]=max(f[x],len);
    43         }
    44     }
    45     for (int i=cnt; i; i--){
    46         int x=q[i]; res[x]=min(res[x],f[x]);
    47         if (f[x] && fa[x]) f[fa[x]]=mx[fa[x]];
    48         f[x]=0;
    49     }
    50 }
    51 
    52 int main(){
    53     scanf("%d%d%d",&n,&len,&fir);
    54     rep(i,1,len-1) scanf("%d",&x),s[i]=x-fir,fir=x;
    55     len--; rep(i,1,len) ext(s[i]);
    56     Radix();
    57     rep(i,2,n){
    58         scanf("%d%d",&len,&fir);
    59         rep(i,1,len-1) scanf("%d",&x),s[i]=x-fir,fir=x;
    60         len--; Go(s,len);
    61     }
    62     rep(i,2,cnt) ans=max(ans,res[i]);
    63     printf("%d
    ",ans+1);
    64     return 0;
    65 }

     

  • 相关阅读:
    swift 中 Self 与self
    Swift 中的泛型
    mac 报文件已损坏 怎么办
    winxp秘钥
    字符串拷贝函数strcpy, strcat, sprintf, strncpy, strncat和snprintf的区别
    【原创】Linux应用程序完整调用自己写的字符设备驱动过程
    idea中新建git分支,并提交到远程github
    (JS-PHP)使用RSA算法进行加密通讯
    Linux日志相关的命令
    hibernate中关于is null的查询
  • 原文地址:https://www.cnblogs.com/HocRiser/p/9441117.html
Copyright © 2011-2022 走看看