[bzoj2946][后缀数组][Poi2000]公共串
来源:互联网 发布:access vba编程入门 编辑:程序博客网 时间:2024/05/17 15:03
2946: [Poi2000]公共串
Time Limit: 3 Sec Memory Limit: 128 MB
Submit: 1178 Solved: 527
[Submit][Status][Discuss]
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3
abcb
bca
acbc
Sample Output
2
HINT
Source
先将每个串都合起来,中间加上一个无限大的字符。(这样不会对heigh产生影响 )考虑怎么在这个总串中找到最长的公共子串。
因为直接求不好求,所以我们先二分。height表示sa[i]和sa[i-1]的lcp,所以我们可以将height数组分类,每一段的头height值总是小于mid值,容易发现只有在这样的height段中,才可能找到最长的公共子串,那么还要满足一个条件就是在这个段中所有的串都出现过。
#include<cstdio>#include<algorithm>#include<string>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>using namespace std;const int N=1100000;int n,m;int x[N],rank[N],w[N],sa[N],hei[N];char sr[N];inline void Sa(){ int m=127,u,v; for(int i=1;i<=m;++i) w[i]=0; for(int i=1;i<=n;++i) w[x[i]=sr[i]]++; for(int i=1;i<=m;++i) w[i]+=w[i-1]; for(int i=n;i>=1;--i) sa[w[x[i]]--]=i; for(int j=1;j<=n;j*=2) { int cnt=0; for(int i=n-j+1;i<=n;++i) rank[++cnt]=i; for(int i=1;i<=n;++i) if(sa[i]>j) rank[++cnt]=sa[i]-j; for(int i=1;i<=m;++i) w[i]=0; for(int i=1;i<=n;++i) w[x[i]]++; for(int i=1;i<=m;++i) w[i]+=w[i-1]; for(int i=n;i>=1;--i) sa[w[x[rank[i]]]--]=rank[i]; m=0; for(int i=1;i<=n;++i) { u=sa[i];v=sa[i-1]; if(x[u]!=x[v]||x[u+j]!=x[v+j]) ++m; rank[u]=m; } if(m==n) break; for(int i=1;i<=n;++i) x[i]=rank[i]; } int j=0; for(int i=1;i<=n;++i) { v=sa[rank[i]-1]; j=max(0,j-1); while(sr[i+j]==sr[v+j]) ++j; hei[rank[i]]=j; }}int K,belong[N];bool vis[6];inline bool check(int x){ int total; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;++i) { if(hei[i]<x) { total=0; for(int j=1;j<=5;++j) total+=vis[j]; memset(vis,0,sizeof(vis)); if(total==K) return 1; } vis[belong[sa[i]]]=1; } total=0; for(int j=1;j<=5;++j) total+=vis[j]; memset(vis,0,sizeof(vis)); if(total==K) return 1; return 0;}int main(){// freopen("2946.txt","r",stdin); int c=1,l,r,len; n=1; l=r=0; cin>>K; for(int i=1;i<=K;++i) { scanf("%s",sr+n); len=strlen(sr+n); n+=len; for(int j=n-len;j<=n;++j) belong[j]=i; sr[n]=c++; ++n; r=max(r,len); } --n; Sa(); while(l+1<r) { int mid=l+r>>1; if(check(mid)) l=mid; else r=mid; } printf("%d",check(r)?r:l);}
阅读全文
0 0
- [bzoj2946][后缀数组][Poi2000]公共串
- [BZOJ2946][Poi2000]公共串 && 后缀自动机
- 【bzoj2946】[Poi2000]公共串 后缀自动机
- bzoj2946 [Poi2000]公共串 后缀自动机
- 【POI2000】【BZOJ2946】公共串
- 【bzoj2946】[Poi2000]公共串
- [BZOJ2946][Poi2000]公共串
- BZOJ2946: [Poi2000]公共串
- 【bzoj2946】[Poi2000]公共串
- BZOJ2946: [Poi2000]公共串
- [POI2000 bzoj2946]公共串
- bzoj2946: [Poi2000]公共串
- BZOJ 2946 [Poi2000]公共串 后缀数组
- 2946: [Poi2000]公共串|哈希|后缀数组
- 2946: [Poi2000]公共串 后缀数组
- 【BZOJ 2946】[Poi2000]公共串 后缀数组
- BZOJ 2946: [Poi2000]公共串 后缀数组
- bzoj2946 [Poi2000]公共串(SA+二分答案 同poj3450)
- Eva's Balance
- win10中微软账户中文名称修改后本地用户文件夹仍为中文名
- java poi 解析excel 输出json 并且拼接字符串显示到jsp
- Realm源码分析之初始化
- leetcode[Arranging Coins]
- [bzoj2946][后缀数组][Poi2000]公共串
- mongoDB的使用
- 【剑指offer】面试题26:树的子结构
- 将form表单封装成对象
- platform_set_drvdata 和 platform_get_drvdata
- 三级联动
- HDU
- 数据仓库在数据挖掘的数据模型
- JUnit4测试方法异常抛出实例