spoj LCS2(多个串的最长公共子序列,后缀自动机)
来源:互联网 发布:直销返利系统源码 编辑:程序博客网 时间:2024/05/19 03:43
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.
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:
alsdfkjfjkdsal
fdjskalajfkdsla
aaaajfaaaa
Output:
2
Notice: new testcases added
多个串的最长公共子序列
和两个串的套路一样,每次记录能匹配到的点,能匹配到的点是一些串的集合,你能到这个点证明这个公共串必定是这个点的串集合里的串之一,那么问题来了。所以每个点记录一下Maxi,为这个点可以在每个串和A串匹配时可以接收的最长公共子串,同时还要往上更新fail 因为当前节点要是可以接受这个子串,那么fail结点必然也可以结束,而且接受的最大长度为max(Maxi[fail[p]],Maxi[p]),但是要和能到当前点的最大长度取min,统计每个串的时候都要对这个最大的取min,这样才是共有的最长子串。最后统计一遍答案就好
#include <bits/stdc++.h>using namespace std;const int maxn = 500000+5;int last,tail,in[maxn],Min[maxn];int Max[maxn],cnt[maxn],vis[maxn];int nxt[maxn][26],fail[maxn];char sa[maxn],sb[maxn];int Maxi[maxn],Mini[maxn];inline void build(char *s){ while(*s) { int p=last,t=++tail,c=*s++-'a'; Max[t]=Max[p]+1; Mini[t]=Max[t]; Maxi[t]=0; while(p&&!nxt[p][c]) nxt[p][c]=t,p=fail[p]; if(p) { int q=nxt[p][c]; if(Max[q]==Max[p]+1) fail[t]=q,Min[t]=Max[q]+1; else { int k=++tail; fail[k]=fail[q]; fail[t]=fail[q]=k; Max[k]=Max[p]+1; Mini[k]=Max[k]; Maxi[k]=0; memcpy(nxt[k],nxt[q],sizeof(nxt[q])); while(p&&nxt[p][c]==q) nxt[p][c]=k,p=fail[p]; } } else fail[t]=Min[t]=1; last=t; }}int b[maxn];int main(){ scanf("%s",sa); last=1,tail=1; build(sa); int hh=strlen(sa); for(int i=1;i<=tail;i++) cnt[Max[i]]++; for(int i=1;i<=hh;i++) cnt[i]+=cnt[i-1]; for(int i=1;i<=tail;i++) b[cnt[Max[i]]--]=i; while(~scanf("%s",sb)) { int h=strlen(sb); int p=1; int len=0; for(int i=0;i<h;i++) { int c=sb[i]-'a'; if(nxt[p][c]) len++,p=nxt[p][c]; else{ while(p&&!nxt[p][c]) p=fail[p]; if(!p) p=1,len=0; else { len=Max[p]+1; p=nxt[p][c]; } } Maxi[p]=max(Maxi[p],len); } for(int i=tail;i>=1;i--) { int p=b[i]; Mini[p]=min(Mini[p],Maxi[p]); if(fail[p]) Maxi[fail[p]]=max(Maxi[p],Maxi[fail[p]]); Maxi[p]=0; } } int ans=0; for(int i=1;i<=tail;i++) { ans=max(ans,Mini[i]); } printf("%d",ans );}
- spoj LCS2(多个串的最长公共子序列,后缀自动机)
- SPOJ 题目1812 LCS2 - Longest Common Substring II(后缀自动机求多个串的最长公共子串)
- SPOJ LCS2(后缀自动机)
- SPOJ LCS2 --后缀自动机
- 【后缀自动机】 SPOJ LCS2
- spoj LCS2 【后缀自动机】
- SPOJ LCS2 后缀自动机
- SPOJ LCS2 后缀自动机
- spoj 1812(两个串的最长公共子串)后缀自动机
- spoj 1812 LCS2 (后缀自动机)
- spoj lcs2 后缀自动机SAM
- SPOJ 1812 LCS2 后缀自动机
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
- SPOJ 题目1811 LCS - Longest Common Substring(后缀自动机求最长公共子串)
- 后缀自动机(多个穿的最长公共子串)spoj1812
- SPOJ LCS 最长公共子串 后缀自动机&后缀树(Ukkonen)
- SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机)
- SPOJ 1812 Longest Common Substring II 后缀自动机求多字符串最长公共子串
- Android启动页面(闪屏页面)的实现
- 未来AI晶片发展有八大新趋势
- python 装饰器理解
- Gradle各版本下载地址
- 编写更好Python程序的5个技巧
- spoj LCS2(多个串的最长公共子序列,后缀自动机)
- Android获取IP地址
- 手机端页面自适应解决方案—rem布局
- Linux系统基础(四)
- java服务器端控制层代码(特别方便)
- IRC扫盲——你可以不会玩QQ,但不能不会IRC!
- 使用TortoiseGit操作分支的创建与合并
- 小白的python之路 Day1
- 上传maven到私服