BZOJ2946: [Poi2000]公共串
2014-12-13 17:45
225 查看
2946: [Poi2000]公共串
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 55 Solved: 33
[Submit][Status]
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。Output
仅一行,一个整数,最长公共子串的长度。Sample Input
3abcb
bca
acbc
Sample Output
2题解:
后缀数组经典做法。
代码:
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<queue> #include<string> #define inf 1000000000 #define maxn 100000 #define maxm 500+100 #define eps 1e-10 #define ll long long #define pa pair<int,int> #define for0(i,n) for(int i=0;i<=(n);i++) #define for1(i,n) for(int i=1;i<=(n);i++) #define for2(i,x,y) for(int i=(x);i<=(y);i++) #define for3(i,x,y) for(int i=(x);i>=(y);i--) #define mod 1000000007 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} return x*f; } int n,m,c[maxn],t1[maxn],t2[maxn],sa[maxn],rk[maxn],h[maxn],a[maxn]; char s[maxn]; bool v[10]; void getsa(int m) { int *x=t1,*y=t2; for0(i,m)c[i]=0; for0(i,n)c[x[i]=s[i]]++; for1(i,m)c[i]+=c[i-1]; for3(i,n,0)sa[--c[x[i]]]=i; for(int k=1;k<=n+1;k<<=1) { int p=0; for2(i,n-k+1,n)y[p++]=i; for0(i,n)if(sa[i]>=k)y[p++]=sa[i]-k; for0(i,m)c[i]=0; for0(i,n)c[x[y[i]]]++; for1(i,m)c[i]+=c[i-1]; for3(i,n,0)sa[--c[x[y[i]]]]=y[i]; swap(x,y);p=0;x[sa[0]]=0; for1(i,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p; if(p>=n)break; m=p; } for1(i,n)rk[sa[i]]=i; for(int i=0,k=0,j;i<n;h[rk[i++]]=k) for(k?k--:0,j=sa[rk[i]-1];s[i+k]==s[j+k];k++); } bool check(int x) { for(int i=1,j=1;j<=n+1;j++) if(h[j]<x||j==n+1) { for1(k,m)v[k]=0; for2(k,i,j-1)v[a[sa[k]]]=1; bool flag=0; for1(k,m)if(!v[k])flag=1; if(!flag)return 1; i=j; } return 0; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); m=read(); for1(i,m) { s ='z'+i; scanf("%s",s+n+1); int t=strlen(s);for2(j,n+1,t-1)a[j]=i; n=t; } s =' '; getsa(128); int l=0,r=n,mid; while(l<=r) { mid=(l+r)>>1; if(check(mid))l=mid+1;else r=mid-1; } printf("%d\n",r); return 0; }
View Code
相关文章推荐
- BZOJ2946 [Poi2000]公共串 【后缀自动机】
- bzoj2946 [Poi2000]公共串(SAM)
- BZOJ2946: [Poi2000]公共串
- bzoj2946: [Poi2000]公共串
- bzoj2946 [Poi2000]公共串 后缀自动机
- Bzoj2946 [Poi2000]公共串
- bzoj2946 [Poi2000]公共串(SAM)
- 【BZOJ】【P2946】【Poi2000】【公共串】【题解】【hash】
- 【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串
- bzoj 2946: [Poi2000]公共串
- 2946: [Poi2000]公共串|哈希|后缀数组
- SPOJ LCS2 Longest Common Substring II + BZOJ 2946 [Poi2000]公共串
- BZOJ 2946 [Poi2000]公共串 后缀数组
- BZOJ2946: [Poi2000]公共串
- BZOJ2946 [Poi2000]公共串 二分+hash
- 2946: [Poi2000]公共串 后缀自动机
- [BZOJ2946][POI2000]公共串(后缀自动机)
- [BZOJ2946][Poi2000]公共串
- Bzoj2946:[POI2000] 最长公共子串
- Bzoj2946:[POI2000] 最长公共子串