刷题集--Longest Common Substring II

题目大意:给出N (N≤10)个长度不超过100000的字符串,求他们的最长公共连续子串。

用后缀数组加二分可在nlog求解,但会了后缀自动机就可以O(n)求解,先对一个串建sam,再匹配余下的,最后沿fa边dfs即可。

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n;char s[N];
struct Sam{
    struct gg{
        int mx,fa,nxt[26];
    }node[N*2];
    int cnt,las,tax[N*2],res[N*2],ans[N*2],id[N*2];
    void init()
    {
        memset(ans,127,sizeof ans);
        las=cnt=1;
    }
    void add(int x)
    {
        int p,np,t,nt;
        p=las,np=las=++cnt;
        node[np].mx=node[p].mx+1;
        while(p&&!node[p].nxt[x])
        {
            node[p].nxt[x]=np;
            p=node[p].fa;
        }
        if(!p)node[np].fa=1;
        else
        {
            t=node[p].nxt[x];
            if(node[t].mx==node[p].mx+1)
                node[np].fa=t;
            else
            {
                nt=++cnt;node[nt].mx=node[p].mx+1;
                memcpy(node[nt].nxt,node[t].nxt,sizeof node[t].nxt);
                node[nt].fa=node[t].fa;
                node[t].fa=node[np].fa=nt;
                for(;node[p].nxt[x]==t;p=node[p].fa)node[p].nxt[x]=nt;
            }
        }
    }
    void rsort()
    {
        for(int i=1;i<=cnt;i++)tax[node[i].mx]++;
        for(int i=1;i<=cnt;i++)tax[i]+=tax[i-1];
        for(int i=cnt;i>=1;i--)id[tax[node[i].mx]--]=i;
    }
    void match(char *s)
    {
        memset(res,0,sizeof res);
        int len=strlen(s+1),ps=1,nx,ft=0;
        for(int i=1;i<=len;i++)
        {
            nx=s[i]-'a';
            if(node[ps].nxt[nx])ps=node[ps].nxt[nx],++ft;
            else
            {
                while(ps&&!node[ps].nxt[nx])ps=node[ps].fa;
                if(ps==0)ps=1,ft=0;
                else ft=node[ps].mx+1,ps=node[ps].nxt[nx];
            }
            res[ps]=max(res[ps],ft);
        }
        for(int i=cnt;i>=1;i--)
        {
            ps=id[i];
            ans[ps]=min(ans[ps],res[ps]);
            res[node[ps].fa]=max(res[node[ps].fa],res[ps]);
        }
    }
    void solve()
    {
        int moha=0;
        for(int i=1;i<=cnt;i++)
            moha=max(moha,min(node[i].mx,ans[i]));
        cout<<moha;  
    }
}sam;
int main()
{
    int len;
    sam.init();
    int cc=0;
    while(~scanf("%s",s+1))
    {
        ++cc;if(s[1]=='P')break;
        if(cc==1)
        {
            len=strlen(s+1);
            for(int j=1;j<=len;j++)
                sam.add(s[j]-'a');
            sam.rsort();
        }
        else sam.match(s);
    }
    sam.solve();
}

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/82686229