后缀自动机 模板题

关于后缀自动机我实在不好意思说些啥,这确实是我学过最难得算法,就到这一刻我还有点小细节没弄懂,但大体都明白了,clj老师不愧是传奇人物,太强啦。

关于后缀数组,详细还是要看陈老师的ppt,结合网上的解释,加油。

转自:http://blog.csdn.net/thy_asdf/article/details/51569443

题目大意:

求两个串的最长公共子串

基本思路:

后缀自动机;

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn = 500000+10;
int n,m;
char a[maxn],b[maxn];

struct TSam{
    int ch[maxn][26],dis[maxn],fa[maxn];
    int tot,root,last;
    void add(int pos){
        int x=a[pos]-'a',p=last,np=++tot;
        last=np,dis[np]=pos;
        for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
        if(!p) fa[np]=root;
        else{
            int q=ch[p][x];
            if(dis[q]==dis[p]+1) fa[np]=q;
            else{
                int nq=++tot;
                dis[nq]=dis[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q],fa[np]=fa[q]=nq;
                for(;ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
            }
        }
    }
}T;

int main(){
    scanf("%s%s",a+1,b+1);
    T.last=T.root=++T.tot;
    n=strlen(a+1),m=strlen(b+1);
    for(int i=1;i<=n;i++) T.add(i);
    int ans=0,len=0,p=T.root;
    for(int i=1;i<=m;i++){
        int x=b[i]-'a';
        if(T.ch[p][x]){
            len++;
            p=T.ch[p][x];
        }
        else{
            while(p&&!T.ch[p][x]) p=T.fa[p];
            if(!p){
                p=T.root;
                len=0;
            }else{
                len=T.dis[p]+1;
                p=T.ch[p][x];
            }
        }
        ans=max(ans,len);
    }
    printf("%d\n",ans);
    return 0;
}

  

posted @ 2017-12-14 17:00  愿~得偿所愿,不负时光  阅读(343)  评论(0编辑  收藏  举报