首页 > 其他 > 详细

LCS - Longest Common Substring

时间:2020-08-19 15:17:08      阅读:66      评论:0      收藏:0      [点我收藏+]

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;
}

LCS - Longest Common Substring

原文:https://www.cnblogs.com/CADCADCAD/p/13529276.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!