[POI2000] 最长公共子串
来源:互联网 发布:wifi满信号网络特别慢 编辑:程序博客网 时间:2024/05/17 11:07
- 从文件中读入单词
- 计算最长公共子串的长度
- 输出结果到文件
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务
输入
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
输出:
仅一行,一个整数,最长公共子串的长度。
样例输入:
3abcbbcaacbc
样例输出:
2
把字符串连在一起后缀数组预处理,然后二分答案,检验:将height<答案的字符串另开一段,最后判断总段数是否等于字符串总数即可
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=50000+100;
char s[maxn];
int sa[maxn]={0},t[maxn]={0},t2[maxn]={0},c[maxn]={0};
int d[maxn]={0},M;
inline int idx(char c){
return c-'A';
}
inline void build_sa(int n,int m){
int *x=t,*y=t2;
for(int i=0;i<m;i++)
c[i]=0;
for(int i=0;i<n;i++)
c[x[i]=d[i]]++;
for(int i=1;i<m;i++)
c[i]+=c[i-1];
for(int i=n-1;i>=0;i--)
sa[--c[x[i]]]=i;
for(int k=1;k<n;k<<=1){
int p=0;
for(int i=n-k;i<n;i++)
y[p++]=i;
for(int i=0;i<n;i++)
if(sa[i]>=k)
y[p++]=sa[i]-k;
for(int i=0;i<m;i++)
c[i]=0;
for(int i=0;i<n;i++)
c[x[y[i]]]++;
for(int i=1;i<m;i++)
c[i]+=c[i-1];
for(int i=n-1;i>=0;i--)
sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;
x[sa[0]]=0;
for(int i=1;i<n;i++){
x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])?p-1:p++;
}
if(p>=n)
break;
m=p;
}
}
int belong[maxn];
int rank[maxn],height[maxn];
inline void getheight(int n){
int h=0;
for(int i=0;i<n;i++)
rank[sa[i]]=i;
for(int i=0;i<n;i++){
if(rank[i]==0) h=0;
else{
int k=sa[rank[i]-1];
if(--h<0)
h=0;
while(d[i+h]==d[k+h])
h++;
}
height[rank[i]]=h;
}
}
int ba[maxn],n;
bool check(int x){
for(int i=1;i<=n;i++){
if(height[i]>=x){
int j=i;
while(height[j]>=x&&j<=n)
j++;
j--;
memset(ba,0,sizeof(ba));
for(int k=i-1;k<=j;k++)
ba[belong[sa[k]]]=true;
int k=1;
while(ba[k]&&k<=M)
k++;
if(k==M+1)
return true;
i=j;
}
}
return false;
}
int main(){
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
scanf("%d",&M);
n=0;
for(int i=1;i<=M;i++){
scanf("%s",s);
for(char *p=s;*p;p++){
d[++n]=*p-'a';
belong[n]=i;
}
if(i<M)
d[++n]=30+i;
}
build_sa(n,100);
getheight(n);
int ans=0;
int l=0,r=n;
while(l+1!=r){
int mid=(l+r)>>1;
if(check(mid))
l=mid;
else r=mid;
}
if(check(r))
ans=r;
else ans=l;
printf("%lld\n",ans);
return 0;
}
- [POI2000] 最长公共子串
- [POI2000] 最长公共子串
- 【POI2000】【BZOJ2946】公共串
- 【bzoj2946】[Poi2000]公共串
- [BZOJ2946][Poi2000]公共串
- BZOJ2946: [Poi2000]公共串
- 【bzoj2946】[Poi2000]公共串
- BZOJ2946: [Poi2000]公共串
- [POI2000 bzoj2946]公共串
- bzoj2946: [Poi2000]公共串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- 最长公共子串
- Jquery的loading插件
- VirtualBox Linux虚拟机与主机SSH互联
- Servlet入门
- Android开发中实现用户注册和登陆的小demo分享
- C语言输入一个数,倒序输出
- [POI2000] 最长公共子串
- Oracle 增加修改删除字段
- Java中instanceof和isInstance区别详解
- kNN与KD-Tree
- jsp include标签引入html文件中文乱码问题解决
- 卷积神经网络池化层和卷积层作用
- c++关键字
- 无监督学习与GAN网络
- WebSocket 是什么原理?为什么可以实现持久连接