SPOJ LCS2 Longest Common Substring II + BZOJ 2946 [Poi2000]公共串
2018-02-24 11:40
232 查看
A string is finite sequence of characters over a non-empty finite set Σ.
In this problem, Σ is the set of lowercase letters.
Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.
Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.
Here common substring means a substring of two or more strings.
fdjskalajfkdsla
aaaajfaaaa
其实这两道题是双倍经验题;
对第一个串建SAM,把后面的串放在这个SAM上跑,记录到达一个节点这一个串的最长的长度,到达一个点需要把它的parent树上的祖先全部更新一遍,对每个记录所有串的最小值,这些节点记录的值的最大值就是答案。
In this problem, Σ is the set of lowercase letters.
Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.
Now your task is a bit harder, for some given strings, find the length of the longest common substring of them.
Here common substring means a substring of two or more strings.
Input
The input contains at most 10 lines, each line consists of no more than 100000 lowercase letters, representing a string.Output
The length of the longest common substring. If such string doesn’t exist, print “0” instead.Example
Input:
alsdfkjfjkdsalfdjskalajfkdsla
aaaajfaaaa
Output:
2Notice:
new testcases added思路
BZOJ是权限题,不放题目描述了;其实这两道题是双倍经验题;
对第一个串建SAM,把后面的串放在这个SAM上跑,记录到达一个节点这一个串的最长的长度,到达一个点需要把它的parent树上的祖先全部更新一遍,对每个记录所有串的最小值,这些节点记录的值的最大值就是答案。
ans=max(节点的答案=min(串到达这个节点的最长长度=max(串到达这个节点的长度)))
代码
#include <cstdio> #include <cstring> #include <algorithm> const int maxn=250000; const int maxk=500000; struct node { node* tr[26]; node* par; int maxl,num; }; struct suffix_automaton { node* qs; node* qlast; node samnode[maxk+10]; int cnt,tmp[maxk+10],ans[maxk+10],ki[maxk+10]; inline int clear() { delete qs; delete qlast; qlast=qs=new node(); cnt=0; return 0; } inline int addchr(int ch) { node* p=qlast; node* np=&samnode[++cnt]; np->maxl=qlast->maxl+1; qlast=np; np->num=cnt; while((p!=NULL)&&(p->tr[ch]==NULL)) { p->tr[ch]=np; p=p->par; } if(p==NULL) { np->par=qs; return 0; } node* q=p->tr[ch]; if(q->maxl!=p->maxl+1) { node* nq=&samnode[++cnt]; nq->maxl=p->maxl+1; nq->num=cnt; memcpy(nq->tr,q->tr,sizeof q->tr); nq->par=q->par; q->par=np->par=nq; while((p!=NULL)&&(p->tr[ch]==q)) { p->tr[ch]=nq; p=p->par; } } else { np->par=q; } return 0; } inline int sortmaxl() { for(register int i=1; i<=cnt; ++i) { ans[i]=samnode[i].maxl; } for(register int i=1; i<=cnt; ++i) { ++tmp[samnode[i].maxl]; } for(register int i=2; i<=cnt; ++i) { tmp[i]+=tmp[i-1]; } for(register int i=cnt; i; --i) { ki[tmp[samnode[i].maxl]--]=i; } return 0; } inline int run(char* s,int len) { node* q=qs; int l=0; memset(tmp,0,sizeof tmp); for(register int i=1; i<=len; ++i) { int ch=s[i]-'a'; while((q!=NULL)&&(q->tr[ch]==NULL)) { q=q->par; } if(q==NULL) { q=qs; l=0; } else { l=std::min(l,q->maxl)+1; q=q->tr[ch]; } tmp[q->num]=std::max(tmp[q->num],l); } for(register int i=cnt; i; --i) { tmp[samnode[ki[i]].par->num]=std::max(tmp[samnode[ki[i]].par->num],tmp[ki[i]]); } for(register int i=1; i<=cnt; ++i) { ans[i]=std::min(ans[i],tmp[i]); } return 0; } inline int lcs() { int a=0; for(register int i=1; i<=cnt; ++i) { a=std::max(a,ans[i]); } return a; } }; suffix_automaton sam; char s[maxn+10]; int main() { scanf("%s",s+1); int len=strlen(s+1); sam.clear(); for(register int i=1; i<=len; ++i) { sam.addchr(s[i]-'a'); } sam.sortmaxl(); while(~scanf("%s",s+1)) { sam.run(s,strlen(s+1)); } printf("%d\n",sam.lcs()); return 0; }
相关文章推荐
- [后缀自动机 模板题] SPOJ 1812 Longest Common Substring II & BZOJ 2946 [Poi2000]公共串
- 【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串
- BZOJ 2946: [Poi2000]公共串
- BZOJ 2946: [Poi2000]公共串 后缀数组
- SPOJ LCS2 Longest Common Substring II
- SPOJ LCS2(Longest Common Substring II-后缀自动机向父亲更新)
- SPOJ 1812 Longest Common Substring II 后缀自动机求多字符串最长公共子串
- BZOJ 2946 [Poi2000]公共串 后缀自动机
- Bzoj2946:[POI2000] 最长公共子串
- 【BZOJ 2946】[Poi2000]公共串 后缀数组
- BZOJ2946: [Poi2000]公共串
- Bzoj2946:[POI2000] 最长公共子串
- SPOJ LCS2 Longest Common Substring II 后缀自动机
- SPOJ LCS2(Longest Common Substring II-后缀自动机向父亲更新)
- 后缀自动机 模板 【Poi2000】 公共串 bzoj 2946
- [BZOJ2946][Poi2000]公共串 && 后缀自动机
- bzoj2946 [Poi2000]公共串(后缀数组 || 后缀自动机)
- SPOJ LCS2 - Longest Common Substring II
- bzoj2946 [Poi2000]公共串
- SPOJ 题目1812 LCS2 - Longest Common Substring II(后缀自动机求多个串的最长公共子串)