LCS - Longest Common Substring

SP1811 LCS - Longest Common Substring

用 sam 进行字符串匹配,建 s 的 sam,然后用 t 在 s 的 sam 上进行匹配,匹配过程中,沿着 Next 转移往下走,如果失配,则沿着 link 链接往上跳,因为 link 链接是该节点的后缀,所以这样跳就不会有遗漏,而且均摊下来跳后缀链接的总复杂度为\(O(n)\)因此不会超时。

// Created by CAD
#include <bits/stdc++.h>
using namespace std;

const int maxn=(2e5+5e4+5)*2;
namespace sam{
    int len[maxn],link[maxn],Next[maxn][26];
    int sz,last;
    void init(){                //记得初始化
        sz=last=0;
        len[0]=0,link[0]=-1;
    }
    void insert(char c){        //插入字符
        int now=++sz;
        len[now]=len[last]+1;
        int p=last;
        while(~p&&!Next[p][c-'a']){
            Next[p][c-'a']=now;
            p=link[p];
        }
        if(p==-1) link[now]=0;
        else{
            int q=Next[p][c-'a'];
            if(len[p]+1==len[q]) link[now]=q;
            else{
                int clone=++sz;
                len[clone]=len[p]+1;
                memcpy(Next[clone],Next[q],sizeof(Next[q]));
                link[clone]=link[q];
                while(~p&&Next[p][c-'a']==q){
                    Next[p][c-'a']=clone;
                    p=link[p];
                }
                link[q]=link[now]=clone;
            }
        }
        last=now;
    }
    int solve(char *s,char *t){
        int ans=0;
        int op=0,last=-1;
        int slen=strlen(s),tlen=strlen(t);
        int now=0;
        while(op<tlen){
            int temp=0;
            while(op<tlen&&Next[now][t[op]-'a']){//如果匹配则沿着转移走下去
                now=Next[now][t[op]-'a'];
                temp=op-last;
                ans=max(ans,temp);
                op++;
            }
            if(temp==0) op++,last++;
            while(~link[now]&&!Next[now][t[op]-'a'])
                //一旦失配,则沿着后缀链接往上跳,直到跳到0或者再次匹配
                now=link[now];
            	last+=temp-len[now];
        }
        return ans;
    }
}

char s[maxn],t[maxn];
int main() {
    sam::init();
    scanf("%s%s",s,t);
    int slen=strlen(s);
    for(int i=0;i<slen;++i) sam::insert(s[i]);
    printf("%d\n",sam::solve(s,t));
    return 0;
}
posted @ 2020-08-19 14:41  caoanda  阅读(120)  评论(0编辑  收藏  举报