bzoj 2946: [Poi2000]公共串
来源:互联网 发布:矩阵lu分解例题 编辑:程序博客网 时间:2024/05/03 20:57
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3
abcb
bca
acbc
abcb
bca
acbc
Sample Output
2
首先一点,root到一个结点的pre包含这个节点的所有后缀。
那么就很好做了!对第一个串建立后缀自动机。然后跑匹配
到每个节点的len的最大值取最小值,然后再把所有最小值求最大值就是答案了
初始每个节点的ans[i]为step[i],为了防止路径超过根到当前点的最长路径
#include<cstdio>#include<string>#include<cstring>#include<iostream>using namespace std;struct sam{ int son[1000001][26],pre[1000001],step[1000001]; int ans[1000001],v[1000001],q[1000001]; int len[1000001]; int last,tot; sam() { last=1; tot=1; } inline void push_back(int v) { tot++; step[tot]=v; } inline void prep() { int i; for(i=1;i<=tot;i++) ans[i]=step[i]; for(i=1;i<=tot;i++) v[step[i]]++; for(i=1;i<=tot;i++) v[i]+=v[i-1]; for(i=tot;i>=1;i--) q[v[step[i]]--]=i; }//基数排序,确定树的遍历 inline void extend(int x) { push_back(step[last]+1); int p=last,np=tot; while(son[p][x]==0&&p!=0) { son[p][x]=np; p=pre[p]; } if(p==0) pre[np]=1; else { int q=son[p][x]; if(step[q]!=step[p]+1) { push_back(step[p]+1); int nq=tot; //memcpy(son[nq],son[q],sizeof(son[q])); int i; for(i=0;i<=25;i++) son[nq][i]=son[q][i]; pre[nq]=pre[q]; pre[q]=pre[np]=nq; while(son[p][x]==q) { son[p][x]=nq; p=pre[p]; } } else pre[np]=q; } last=np; } inline void build() { string x; cin>>x; int lx=x.size(); int i; for(i=0;i<=lx-1;i++) extend(x[i]-'a'); } inline void solve() { memset(len,0,sizeof(len)); string x; cin>>x; int lx=x.size(); int p=1,tmp=0; int i; for(i=0;i<=lx-1;i++) { int xt=x[i]-'a'; while(son[p][xt]==0&&p!=0) p=pre[p]; if(p==0) { p=1; tmp=0; } else { tmp=min(tmp,step[p])+1; p=son[p][xt]; } len[p]=max(len[p],tmp); } for(i=tot;i>=1;i--) len[pre[q[i]]]=max(len[pre[q[i]]],len[q[i]]); for(i=1;i<=tot;i++) ans[i]=min(ans[i],len[i]); }}sam;int main(){ int n; scanf("%d",&n); sam.build(); int i; sam.prep(); for(i=2;i<=n;i++) sam.solve(); int ans=0; for(i=1;i<=sam.tot;i++) ans=max(ans,sam.ans[i]); printf("%d\n",ans); return 0;}
0 0
- bzoj 2946: [Poi2000]公共串
- BZOJ 2946 [Poi2000]公共串
- BZOJ 2946 Poi2000 公共串 后缀自动机
- BZOJ 2946 [Poi2000]公共串 后缀数组
- 【BZOJ 2946】[Poi2000]公共串 后缀数组
- bzoj 2946: [Poi2000]公共串 后缀自动机
- BZOJ 2946 [Poi2000]公共串 后缀自动机
- BZOJ 2946: [Poi2000]公共串 后缀数组
- bzoj 2946: [Poi2000]公共串 (后缀自动机)
- 后缀自动机 模板 【Poi2000】 公共串 bzoj 2946
- 【BZOJ】【P2946】【Poi2000】【公共串】【题解】【hash】
- [后缀自动机 模板题] SPOJ 1812Longest Common Substring II & BZOJ 2946 [Poi2000]公共串
- 2946: [Poi2000]公共串 二分+hash
- 2946: [Poi2000]公共串|哈希|后缀数组
- 2946: [Poi2000]公共串 后缀数组
- 2946: [Poi2000]公共串 后缀自动机
- 2946: [Poi2000]公共串 (hash+二分)
- 【POI2000】【BZOJ2946】公共串
- JAVA环境变量配置
- 创业者探访腾讯8小时后说:仰望中激发内心坚持
- macbook搭建apache多站点
- Perforce初体验
- 接口和抽象类区别 .
- bzoj 2946: [Poi2000]公共串
- JetBrains PhpStorm 8.0.3 关联 PHP
- DL4NLP---第一讲
- DOM解析XML
- Ubuntu安装virtualbox
- leetcode 二叉树的遍历栈的实现 Preorder Traversal Inorder Traversal Postorder Traversal
- 16. 3Sum Closest
- spring mvc ModelAndView 404 错误
- JAVA学习第7天(15-6-25)