spoj 1812 LCS2 - Longest Common Substring II



题意:

给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串。



限制:

1 <= n <= 10

|A[i]| <= 1e5



思路:

和spoj 1811 LCS几乎相同的做法



把当中一个A建后缀自己主动机

考虑一个状态s, 假设A之外的其它串对它的匹配长度各自是a[1], a[2], ..., a[n - 1], 那么min(a[1], a[2], ..., a[n - 1], Max(s))就能够更新答案。

注意:

我们求的是对于随意一个Right集合中的r。最大的匹配长度。那么对于一个状态s。它的结果自然也能够作为它Parent的结果,我们能够从底到上更新一遍。

这个能够通过一次拓扑排序搞定。

/*spoj 1812 LCS2 - Longest Common Substring II
题意:
给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串。 限制:
1 <= n <= 10
|A[i]| <= 1e5
思路:
和spoj 1811 LCS几乎相同的做法 把当中一个A建后缀自己主动机
考虑一个状态s, 假设A之外的其它串对它的匹配长度各自是a[1], a[2], ..., a[n - 1], 那么min(a[1], a[2], ..., a[n - 1], Max(s))就能够更新答案。 注意:
我们求的是对于随意一个Right集合中的r,最大的匹配长度。那么对于一个状态s,它的结果自然也能够作为它Parent的结果。我们能够从底到上更新一遍。
这个能够通过一次拓扑排序搞定。 */
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5 + 5;
char str[15][N]; int maxx[2 * N], minn[2 * N]; struct SAM {
struct Node {
int fa, ch[27];
int val;
void init() {
fa = val = 0;
memset(ch, 0, sizeof(ch));
}
} node[2 * N]; int tot;
int new_node() {
node[++tot].init();
return tot;
} int root, last;
void init() {
root = last = tot = 1;
node[0].init();
node[1].init();
} void add(int x) {
int p = last;
int np = new_node(); node[np].val = node[p].val + 1;
while(p && node[p].ch[x] == 0) {
node[p].ch[x] = np;
p = node[p].fa;
}
if(p == 0)
node[np].fa = root;
else {
int q = node[p].ch[x];
if(node[p].val + 1 == node[q].val)
node[np].fa = q;
else {
int nq = new_node(); node[nq].val = node[p].val + 1;
memcpy(node[nq].ch, node[q].ch, sizeof(node[q].ch));
node[nq].fa = node[q].fa;
node[q].fa = node[np].fa = nq;
while(p && node[p].ch[x] == q) {
node[p].ch[x] = nq;
p = node[p].fa;
}
}
}
last = np;
}
void debug() {
for(int i = 1; i <= tot; ++i) {
printf("id=%d, fa=%d, step=%d, ch=[ ", i, node[i].fa, node[i].val);
for(int j = 0; j < 26; ++j) {
if(node[i].ch[j])
printf("%c,%d ", j+'a', node[i].ch[j]);
}
puts("]");
}
} void gao(int);
} sam; int du[2 * N];
int que[2 * N], fr, ta;
int b[2 * N], b_tot; void SAM::gao(int n) {
init();
int len1 = strlen(str[0]);
for(int i = 0; i < len1; ++i)
add(str[0][i] - 'a'); //debug(); b_tot = fr = ta = 0;
for(int i = 1; i <= tot; ++i)
++du[node[i].fa];
for(int i = 1; i <= tot; ++i)
if(du[i] == 0) que[ta++] = i, b[b_tot++] = i;
while(fr != ta) {
int u = que[fr++];
int v = node[u].fa;
--du[v];
if(du[v] == 0) que[ta++] = v, b[b_tot++] = v;
} for(int i = 1; i <= tot; ++i)
minn[i] = node[i].val;
for(int i = 1; i < n; ++i) {
int len = strlen(str[i]);
int p = root;
int tmp = 0;
fill(maxx, maxx + tot + 1, 0);
for(int j = 0; j < len; ++j) {
int x = str[i][j] - 'a';
if(node[p].ch[x]) {
++tmp;
p = node[p].ch[x];
} else {
while(p && node[p].ch[x] == 0)
p = node[p].fa;
if(p) {
tmp = node[p].val + 1;
p = node[p].ch[x];
} else {
p = root;
tmp = 0;
}
}
maxx[p] = max(maxx[p], tmp);
}
for(int j = 0; j < tot; ++j) {
int u = b[j];
minn[u] = min(minn[u], maxx[u]);
int v = node[u].fa;
maxx[v] = max(maxx[v], maxx[u]);
}
}
int ans = 0;
for(int i = 1; i <= tot; ++i)
ans = max(ans, minn[i]);
printf("%d\n", ans);
} int main() {
int n = 0;
while(scanf("%s", str[n]) != EOF) ++n;
sam.gao(n);
return 0;
}

最新文章

  1. a0=1、a1=1、a2=a1+a0、a3=a2+a1,以此类推,请写代码用递归算出a30?
  2. Android开发学习笔记:Intent的简介以及属性的详解【转】
  3. 【Telnet】使用Telnet协议连接到远程Shell执行脚本
  4. NHibernate系列文章十九:NHibernate关系之多对多关系(附程序下载)
  5. halcon摄像机标定
  6. 区分DPI、分辨率(PPI)、图像的物理大小、像素宽度
  7. 理解matplotlib绘图
  8. C语言中的内存压缩技术
  9. (转)LR监控Linux系统性能计数器详解
  10. POST 一张 图像的调试来认识 http post
  11. hdu 1358 KMP的next数据运用
  12. php的ftp类
  13. iOS 百度地图 小的特点demo
  14. Apache MINA NioSocketAcceptor类的实现
  15. COGS 2479. [HZOI 2016]偏序 [CDQ分治套CDQ分治 四维偏序]
  16. Ruby入坑指南
  17. C# 数独算法——LINQ+委托
  18. vue展示dicom文件,医疗系统。
  19. 内核中 subsys_initcall 以及初始化标号
  20. 用ImageSwitcher实现显示图片(更改图片时有动画效果)

热门文章

  1. BZOJ 3595: [Scoi2014]方伯伯的Oj Splay + 动态裂点 + 卡常
  2. javascript的prototype经典使用场景
  3. Qt的widget与Button添加图片
  4. group by两个条件
  5. 【牛客小白月赛6】 C 桃花 - 树上最长路
  6. idea cannot download sources解决办法
  7. PermGen space OOM 记录
  8. 利用Merge into 改写Update SQL 一例
  9. PHP编译参数configure配置详解(持续更新中)
  10. leetcode-832翻转图像