[SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串
题目链接:http://www.spoj.com/problems/LCS2/
其实两个串的LCS会了,多个串的LCS也就差不多了。
我们先用一个串建立后缀自动机,然后其它的串在上面跑。跑的时候算出每一个位置能往左扩展的最大长度也就是LCS。
于是对于每一个状态维护mx数组,表示当前串与SAM在此状态的LCS值。对于一个状态取所有mx中的最小值,然后答案就是所有状态最小值中的最大值,证明显然。
两个串的时候不用拿一个状态更新其祖先状态,但是这里需要。SAM是一个DAG图,我们通过l数组来基数排序,从叶子开始一层一层向上更新就行了。实现有点妙,具体看代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char s[];
int sz=,la,rt,len;
int l[],ch[][],fa[],mn[];
void Extend(int c){
int end=++sz,tmp=la;
l[end]=mn[end]=l[tmp]+;
while(tmp&&!ch[tmp][c]){
ch[tmp][c]=end;
tmp=fa[tmp];
}
if(!tmp) fa[end]=rt;
else{
int ne=ch[tmp][c];
if(l[tmp]+==l[ne]) fa[end]=ne;
else{
int np=++sz;
memcpy(ch[np],ch[ne],sizeof(ch[ne]));
l[np]=mn[np]=l[tmp]+;
fa[np]=fa[ne];
fa[end]=fa[ne]=np;
while(tmp&&ch[tmp][c]==ne){
ch[tmp][c]=np;
tmp=fa[tmp];
}
}
}
la=end;
}
int c[],a[];
int mx[];
void Radixsort(){
for(int i=;i<=sz;i++) c[l[i]]++;
for(int i=;i<=len;i++) c[i]+=c[i-];
for(int i=sz;i>=;i--) a[c[l[i]]--]=i;
}
void Solve(){
while(scanf("%s",s+)!=EOF){
int o=rt,lcs=;
for(int i=;s[i];i++){
int c=s[i]-'a';
if(ch[o][c]){
o=ch[o][c];
mx[o]=max(mx[o],++lcs);
}
else{
while(o&&!ch[o][c]) o=fa[o];
if(!o){
o=rt;
lcs=;
}
else{
lcs=l[o]+;
o=ch[o][c];
mx[o]=max(mx[o],lcs);
}
}
}
for(int i=sz;i>=;i--){
int o=a[i];
mn[o]=min(mn[o],mx[o]);
if(fa[o]) mx[fa[o]]=max(mx[fa[o]],mx[o]);
mx[o]=;
}
}
}
int main(){
rt=la=++sz;
scanf("%s",s+);
len=strlen(s+);
for(int i=;i<=len;i++) Extend(s[i]-'a');
Radixsort();
Solve();
int ans=;
for(int i=;i<=sz;i++) ans=max(ans,mn[i]);
printf("%d\n",ans);
return ;
}
[SPOJ1812]Longest Common Substring II 后缀自动机 多个串的最长公共子串的更多相关文章
- SPOJ LCS2 - Longest Common Substring II 后缀自动机 多个串的LCS
LCS2 - Longest Common Substring II no tags A string is finite sequence of characters over a non-emp ...
- 2018.12.15 spoj1812 Longest Common Substring(后缀自动机)
传送门 后缀自动机模板题. 题意简述:求两个字串的最长公共子串长度. 对其中一个构建后缀自动机,用另外一个在上面跑即可. 代码: #include<bits/stdc++.h> #defi ...
- SPOJ 1812 LCS2 - Longest Common Substring II (后缀自动机、状压DP)
手动博客搬家: 本文发表于20181217 23:54:35, 原地址https://blog.csdn.net/suncongbo/article/details/85058680 人生第一道后缀自 ...
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...
- SPOJ LCS2 Longest Common Substring II ——后缀自动机
后缀自动机裸题 #include <cstdio> #include <cstring> #include <iostream> #include <algo ...
- 【SPOJ】Longest Common Substring(后缀自动机)
[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...
- spoj - Longest Common Substring(后缀自动机模板题)
Longest Common Substring 题意 求两个串的最长公共子串. 分析 第一个串建后缀自动机,第二个串在自动机上跑,对于自动机上的结点(状态)而言,它所代表的最大长度为根结点到当前结点 ...
- spoj 1812 LCS2 - Longest Common Substring II (后缀自己主动机)
spoj 1812 LCS2 - Longest Common Substring II 题意: 给出最多n个字符串A[1], ..., A[n], 求这n个字符串的最长公共子串. 限制: 1 < ...
- SPOJ1812 Longest Common Substring II
题意 A string is finite sequence of characters over a non-empty finite set Σ. In this problem, Σ is th ...
随机推荐
- xcode7 怎样真机測试
1. 下载xcode7 能够通过訪问 https://developer.apple.com/xcode/downloads/ 下载最新的xcode7的版本号 只是官网的下载速度太慢了,这个最好百度一 ...
- udhcp源码详解(五) 之DHCP包--options字段
中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...
- Linq To Entities中的动态排序
换了工作有一个月了,一样的工作.一样的代码.一样的体力活仍就…… Linq To Entityes 也是不新玩意了,近半年来也一直与之打交道,但一直也没对其深究过.今天新加的功能要对所有列支持排序,这 ...
- IOS开发之----常用的基本GDB命令【转】
原文地址:http://blog.sina.com.cn/s/blog_71715bf801016d2y.html gdb不是万能的,可是没有gdb却是万万不能的.这里给大家简单介绍下iOS开发中最基 ...
- Codeforces 440 D. Berland Federalization 树形DP,记录DP
题目链接:http://codeforces.com/contest/440/problem/D D. Berland Federalization Recently, Berland faces ...
- chrome浏览器世界之窗浏览器的收藏夹在哪?
今天心血来潮,用一个查重软件删除重复文件,结果把chrome浏览器和世界之窗浏览器的收藏夹给删除了,导致我保存的好多网页都没有了,在浏览器本身和网上都没有找到这两个浏览器默认的收藏夹在哪个位置,只好用 ...
- 集成到Buildroot中的Helloword程序【转】
本文转载自:http://www.openloongson.org/forum.php?mod=viewthread&tid=85 本帖最后由 gt945 于 2015-7-5 17:06 编 ...
- Expression Blend实例中文教程系列
Expression Blend实例中文教程系列 本系列文章均转载:银光中国 时间:2010-04-09 09:20责任编辑:银光中国网 点击:次 Expression Blend实例中文教程系列由C ...
- 【转】Java 并发编程:核心理论
并发编程是Java程序员最重要的技能之一,也是最难掌握的一种技能.它要求编程者对计算机最底层的运作原理有深刻的理解,同时要求编程者逻辑清晰.思维缜密,这样才能写出高效.安全.可靠的多线程并发程序.本系 ...
- 实现的是Linux和Windows之间的一种共享--samba
samba 基本配置及自定义控制 https://www.cnblogs.com/l-hh/p/9473937.html Samba简介: Samba实现的是Linux和Windows之间的一种共享, ...