codevs 3160 最长公共子串(SAM)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 3160 最长公共子串(SAM)相关的知识,希望对你有一定的参考价值。
3160 最长公共子串
题目描述 Description
给出两个由小写字母组成的字符串,求它们的最长公共子串的长度。
输入描述 Input Description
读入两个字符串
输出描述 Output Description
输出最长公共子串的长度
样例输入 Sample Input
yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother
样例输出 Sample Output
27
数据范围及提示 Data Size & Hint
单个字符串的长度不超过100000
【思路】
SAM求LCS
【代码】
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 const int N = 2*1e5+10; 6 7 char s[N]; 8 int sz,root,last,fa[N],ch[N][26],l[N],n; 9 10 void add(int x) { 11 int c=s[x]-‘a‘; 12 int p=last,np=++sz; last=np; 13 l[np]=x+1; 14 for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np; 15 if(!p) fa[np]=root; 16 else { 17 int q=ch[p][c]; 18 if(l[p]+1==l[q]) fa[np]=q; 19 else { 20 int nq=++sz; l[nq]=l[p]+1; 21 memcpy(ch[nq],ch[q],sizeof(ch[q])); 22 fa[nq]=fa[q]; 23 fa[np]=fa[q]=nq; 24 for(;p&&q==ch[p][c];p=fa[p]) ch[p][c]=nq; 25 } 26 } 27 } 28 void build() { 29 root=last=++sz; 30 scanf("%s",s); 31 n=strlen(s); 32 for(int i=0;i<n;i++) add(i); 33 } 34 void lcs() { 35 scanf("%s",s); 36 n=strlen(s); 37 int p=root,ans=0,len=0; 38 for(int i=0;i<n;i++) { 39 int c=s[i]-‘a‘; 40 if(ch[p][c]) { len++; p=ch[p][c]; } 41 else { 42 for(;p&&!ch[p][c];p=fa[p]); 43 if(!p) { p=root; len=0; } 44 else { 45 len=l[p]+1; p=ch[p][c]; 46 } 47 } 48 if(len>ans) ans=len; 49 } 50 printf("%d",ans); 51 } 52 53 int main() { 54 build(); 55 lcs(); 56 return 0; 57 }
以上是关于codevs 3160 最长公共子串(SAM)的主要内容,如果未能解决你的问题,请参考以下文章