您的位置:首页 > 其它

code vs 3160 最长公共子串(后缀自动机)

2016-12-19 20:52 399 查看
题目描述 Description

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

输入描述 Input Description

读入两个字符串

输出描述 Output Description

输出最长公共子串的长度

样例输入 Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother


样例输出 Sample Output

27

数据范围及提示 Data Size & Hint

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

题解:后缀自动机。

对其中的一个串建立后缀自动机,然后用另一个串在自动机上匹配。类似在AC自动机上的匹配过程,匹配不上了跳转到parent指针(指的是记录的是上一个可以接收后缀的结点(如果当前结点可以接收新的后缀,那么parent指向的结点也一定可以接收后缀)),然后进行匹配。另外l[i]记录的是从根节点到当前节点的最长距离。

匹配上的最长的长度即为最长公共子串。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 200003
using namespace std;
int n,m,ch
[30],fa
,a
,l
,np,nq,p,q,last,cnt,root;
char s
,s1
;
void extend(int x)
{
int c=a[x];
p=last; np=++cnt; last=np;
l[np]=x;
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=++cnt; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof ch[nq]);
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
}
int solve()
{
int tmp=0,ans=0;
for (int i=1;i<=m;i++) {
int c=s1[i]-'a';
if (ch[p][c]) p=ch[p][c],tmp++;
else {
while (p&&!ch[p][c]) p=fa[p];
if (!p) p=1,tmp=0;
else {
tmp=l[p]+1;
p=ch[p][c];
}
}
ans=max(ans,tmp);
}
return ans;
}
int main()
{
freopen("a.in","r",stdin);
scanf("%s",s+1);
n=strlen(s+1); last=root=++cnt;
for (int i=1;i<=n;i++) a[i]=s[i]-'a';
for (int i=1;i<=n;i++) extend(i);
scanf("%s",s1+1);
m=strlen(s1+1);
printf("%d",solve());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: