Longest Common Substring SPOJ - LCS(后缀自动机)

题目链接

题意:求两个串的最长公共子串长度

思路:对a串建sam,b串跑

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=250010;
char s[maxn];
struct Suffix_Automaton{
    //basic
    int nxt[maxn*2][26], fa[maxn*2], l[maxn*2];
    int last,cnt;
    int match_len[maxn*2], match_times[maxn*2];
    int label[maxn*2], mx[maxn*2];
    Suffix_Automaton(){ clear(); }
    void clear(){
        last =cnt=1;
        fa[1]=l[1]=0;
        memset(nxt[1],0,sizeof nxt[1]);
        for (int i=0;i<maxn*2;i++) match_len[i] = INT_MAX;
    }
    void init(char *s){
        while (*s){
            add(*s-'a');s++;
        }
    }
    void add(int c){
        int p = last;
        int np = ++cnt;
        memset(nxt[cnt],0,sizeof nxt[cnt]);
        l[np] = l[p]+1;last = np;
        while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p];
        if (!p)fa[np]=1;
        else{
            int q = nxt[p][c];
            if (l[q]==l[p]+1)fa[np] =q;
            else{
                int nq = ++ cnt;
                l[nq] = l[p]+1;
                memcpy(nxt[nq],nxt[q],sizeof (nxt[q]));
                fa[nq] =fa[q];fa[np] = fa[q] =nq;
                while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p];
            }
        }
    }
    void run(char * s,int Label){
        vector<pair<int,int> > nodes;
        vector<int> a,b;
        int now = 1, len = 0;
        while (*s){
            int ch = *s - 'a';
            while (now != 1 and !nxt[now][ch]){
                now = fa[now];
                len = l[now];
            }
            if (nxt[now][ch]){
                now = nxt[now][ch];
                len ++;
            }
            nodes.push_back(make_pair(now,len));
            a.push_back(now);
            s ++;
        }
        auto cmp = [&](int x,int y){
            return l[x] > l[y];
        };
        sort(a.begin(),a.end(),cmp);
        a.erase(unique(a.begin(),a.end()),a.end());
        for (int x : a){
            int temp = x;
            while (temp != 1 and label[temp] != Label){
                b.push_back(temp);
                label[temp] = Label;
                mx[temp] = 0;
                temp = fa[temp];
            }
        }
        sort(b.begin(),b.end(),cmp);
        for (auto pr : nodes){
            mx[pr.first] = max(mx[pr.first],pr.second);
        }
        for (int x : b){
            mx[fa[x]] = max(mx[fa[x]],l[fa[x]]);
            match_len[x] = min(match_len[x],mx[x]);
            match_times[x] ++;
        }
    }
    ll calc(int tot_times){
        ll tot = 0;
        for (int i = 1;i <= cnt;i ++){
            if (match_times[i] == tot_times){
                tot += max(0,match_len[i] - l[fa[i]]);
            }
        }
        return tot;
    }
    int lcs(char *s)
    {
        int n=strlen(s);
        int cur=1;
        int ans=0;
        int y=0;
        for(int i=0;i<n;i++)
        {
            int c=s[i]-'a';
            if(!nxt[cur][c])
            {
                while(cur&&!nxt[cur][c])
                    cur=fa[cur];
                y=l[cur]+1;
            }
            else
            {
                y++;
            }
            cur=cur?nxt[cur][c]:1;
            if(cur==1)
                y=0;
            ans=max(y,ans);
        }
        return ans;
     } 
}sam;
int main()
{
    scanf("%s",&s);
    int n=strlen(s);
    sam.init(s);
    scanf("%s",s);
    printf("%d\n",sam.lcs(s));
 }

 

posted @ 2020-10-08 17:00  Ldler  Views(78)  Comments(0Edit  收藏  举报