COJ885 LCS???

试题描述
输入两个字符串A、B,输出他们的最长连续公共子串长度。
输入
第一行为一个字符串A。 第二行为一个字符串B。
输出
输出他们的最长连续公共子串长度。
输入示例
ababab bababbabb
输出示例
5
其他说明
1<=|A|,|B|<=100000 A、B均由小写字母a或b组成。

水水哒SAM

将A建立SAM,将B在A上运行,同时维护当前节点的最多匹配长度

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}
const int maxn=200010;
int l[maxn],fa[maxn],to[maxn][2],last=1,cnt=1;
void extend(int c) {
    int p,q,np,nq;
    p=last;l[np=last=++cnt]=l[p]+1;
    for(;!to[p][c];p=fa[p]) to[p][c]=np;
    if(!p) fa[np]=1;
    else {
        q=to[p][c];
        if(l[p]+1==l[q]) fa[np]=q;
        else {
            l[nq=++cnt]=l[p]+1;
            memcpy(to[nq],to[q],sizeof(to[nq]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            for(;to[p][c]==q;p=fa[p]) to[p][c]=nq;
        }
    }
}
char s[maxn];
int main() {
    scanf("%s",s);int n=strlen(s),p=1,ans=0,cur=0;
    rep(0,n-1) extend(s[i]-'a');
    scanf("%s",s);n=strlen(s);
    rep(0,n-1) {
        int c=s[i]-'a';
        if(to[p][c]) p=to[p][c],cur++;
        else {
            while(p&&!to[p][c]) p=fa[p];
            if(!p) p=1,cur=0;
            else cur=l[p]+1,p=to[p][c];
        }
        ans=max(ans,cur);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2015-06-28 19:27  wzj_is_a_juruo  阅读(232)  评论(0编辑  收藏  举报