spoj 1811 Longest Common Substring (第一道后缀自动机)

来源:互联网 发布:淘宝如何签署食品协议 编辑:程序博客网 时间:2024/05/27 02:31

题意:

给出连个串求两个串的最长公共子串。

题解:

dp肯定过不了复杂度高。后缀数组可以过。我用后缀自动机做,第一次写后缀自动机,举得和ac自动机相似都是一种状态转移图。参考了大牛的模板自己改了下写出自己的模板。

这题将第一个串加入后缀自动机,然后去匹配第二个串。很裸的题目。

#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))typedef long long ll;const int oo=0x3f3f3f3f;const ll OO=1LL<<61;const int MOD=10007;const int maxn=260000;const int SIZE=510000;const int type=26;char s1[maxn],s2[maxn];struct SuffixAutoMaton{    int next[SIZE][type],fa[SIZE],len[SIZE];    int tol,last;    int newNode(int x){        len[tol]=x;        fa[tol]=-1;        for(int i=0;i<type;i++){            next[tol][i]=-1;        }        tol++;        return tol-1;    }    void Init(){        tol=0;        last=newNode(0);    }    void add(int k){        int now=last;        int end=newNode(len[now]+1);///end是结尾态        while(now!=-1&&next[now][k]==-1){            next[now][k]=end;            now=fa[now];        }        if(now==-1) fa[end]=0;        else{            int nxt=next[now][k];///下个节点            ///两种情况:            if(len[now]+1==len[nxt]) fa[end]=nxt;            else{                int cnxt=newNode(len[now]+1);///添加的辅助节点                ///接下来将nxt全部复制个cnxt                for(int i=0;i<type;i++)next[cnxt][i]=next[nxt][i];                fa[cnxt]=fa[nxt];                fa[nxt]=fa[end]=cnxt;                while(now!=-1&&next[now][k]==nxt){                    next[now][k]=cnxt;                    now=fa[now];                }            }        }        last=end;    }    void Insert(char buff[]){        int len1=strlen(buff);        for(int i=0;i<len1;i++)            add(buff[i]-'a');    }    int Search(char buff[]){        int len2=strlen(buff);        int now=0,ans=0,maxlen=0;        for(int i=0;i<len2;i++){            int k=buff[i]-'a';            if(next[now][k]!=-1){                maxlen++;                now=next[now][k];            }else{                while(now!=-1&&next[now][k]==-1)now=fa[now];                if(now==-1){///失配从0开始                    maxlen=0;                    now=0;                }                else{                    maxlen=len[now]+1;                    now=next[now][k];                }            }            ans=max(maxlen,ans);        }        return ans;    }}sam;int main(){    while(scanf("%s",s1)!=EOF){        sam.Init();        scanf("%s",s2);        sam.Insert(s1);        printf("%d\n",sam.Search(s2));    }    return 0;}



0 0
原创粉丝点击