您的位置:首页 > 其它

codevs 3160 最长公共子串(SAM)

2016-02-18 20:21 501 查看

3160 最长公共子串

题目描述 Description

给出两个由小写字母组成的字符串,求它们的最长公共子串的长度。

输入描述 Input Description

读入两个字符串

输出描述 Output Description

输出最长公共子串的长度

样例输入 Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother


样例输出 Sample Output

27

数据范围及提示 Data Size & Hint

单个字符串的长度不超过100000

【思路】

  SAM求LCS

【代码】

#include<cstdio>
#include<cstring>
using namespace std;

const int N = 2*1e5+10;

char s
;
int sz,root,last,fa
,ch
[26],l
,n;

void add(int x) {
int c=s[x]-'a';
int p=last,np=++sz; last=np;
l[np]=x+1;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=root;
else {
int q=ch[p][c];
if(l[p]+1==l[q]) fa[np]=q;
else {
int nq=++sz; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(;p&&q==ch[p][c];p=fa[p]) ch[p][c]=nq;
}
}
}
void build() {
root=last=++sz;
scanf("%s",s);
n=strlen(s);
for(int i=0;i<n;i++) add(i);
}
void lcs() {
scanf("%s",s);
n=strlen(s);
int p=root,ans=0,len=0;
for(int i=0;i<n;i++) {
int c=s[i]-'a';
if(ch[p][c]) { len++; p=ch[p][c]; }
else {
for(;p&&!ch[p][c];p=fa[p]);
if(!p) { p=root; len=0; }
else {
len=l[p]+1; p=ch[p][c];
}
}
if(len>ans) ans=len;
}
printf("%d",ans);
}

int main() {
build();
lcs();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: