【bzoj2946】[Poi2000]公共串 后缀自动机
来源:互联网 发布:vision软件怎么画图 编辑:程序博客网 时间:2024/05/17 10:52
Description
给出几个由小写字母构成的单词,求它们最长的公共子串的长度。
任务:
l 读入单词
l 计算最长公共子串的长度
l 输出结果
Input
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
Output
仅一行,一个整数,最长公共子串的长度。
Sample Input
3abcbbcaacbc
Sample Output
2
HINT
Source
.
把第一个串建后缀自动机
然后拿其它串在上面跑,记录每个串匹配到这个点的最大长度,然后在parent树上保存子树最小值(还有和val取min),然后对于所有串取最大值…
说的简单,代码…
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;const int SZ = 100010;const int INF = 1000000010;struct sam_node{ sam_node *ch[30],*par; int val,ans[5];}T[SZ], *root, *last;int Tcnt = 0;sam_node* newnode(int x){ sam_node *k = T + (Tcnt ++); k -> val = x; memset(k -> ch,0,sizeof(k -> ch)); k -> par = 0; memset(k -> ans,0,sizeof(k -> ans)); return k;}void insert(int x){ sam_node *p = last,*np = newnode(last -> val + 1); while(p && !p -> ch[x]) p -> ch[x] = np,p = p -> par; if(!p) np -> par = root; else { sam_node *q = p -> ch[x]; if(q -> val == p -> val + 1) np -> par = q; else { sam_node *nq = newnode(p -> val + 1); memcpy(nq -> ch,q -> ch,sizeof(nq -> ch)); nq -> par = q -> par; q -> par = np -> par = nq; while(p && p -> ch[x] == q) p -> ch[x] = nq,p = p -> par; } } last = np;}void find(char s[],int id){ int l = strlen(s); sam_node *p = root; for(int i = 0,len = 0;i < l;i ++) { int c = s[i] - 'a' + 1; if(p -> ch[c]) { len ++; p = p -> ch[c]; } else { while(p != root && !p -> ch[c]) p = p -> par; len = p -> val; if(p -> ch[c]) p = p -> ch[c],len ++; } p -> ans[id] = max(p -> ans[id],min(p -> val,len)); } for(int i = Tcnt - 1;i >= 1;i --) { sam_node *k = T + i; k -> par -> ans[id] = min(k -> par -> val,max(k -> par -> ans[id],k -> ans[id])); }}void init(){ root = newnode(0); last = root;}int n;int dfs(sam_node *p){ int ans = INF; for(int i = 1;i < n;i ++) ans = min(ans,p -> ans[i]); for(int i = 1;i <= 26;i ++) if(p -> ch[i]) ans = max(ans,dfs(p -> ch[i])); return ans;}char s[SZ];int main(){ init(); scanf("%d",&n); scanf("%s",s); int l = strlen(s); for(int i = 0;i < l;i ++) insert(s[i] - 'a' + 1); for(int i = 1;i < n;i ++) { scanf("%s",s); find(s,i); } printf("%d",dfs(root)); return 0;}/*3abdabdababd*/
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]公共串 后缀自动机
- bzoj 2946: [Poi2000]公共串 后缀自动机
- BZOJ 2946 [Poi2000]公共串 后缀自动机
- bzoj 2946: [Poi2000]公共串 (后缀自动机)
- 后缀自动机 模板 【Poi2000】 公共串 bzoj 2946
- Vijos P1911珠心算测验
- complex_test.cpp尽可能注释
- CodeForces 609 A. USB Flash Drives(贪心)
- awk学习 【转】
- Operating Systems: Three Easy Pieces阅读笔记(四)FILE SYSTEM- VSFC&FSCK
- 【bzoj2946】[Poi2000]公共串 后缀自动机
- linux PV操作理解
- Action实现ModelDriven接口后的运行流程
- 安卓通知的使用系列2:状态栏通知和自定义状态栏通知通知
- Java多线程之停止一个线程
- 水晶报表繁体转简体心得:之一 RPT文件篇
- uva10003(区间dp,提供两种枚举顺序)
- hdu1281二分图匹配
- 韩顺平XML学习2