题意:n个字符串(n<=10)求最长公共子串的长度

前置技能点:https://www.cnblogs.com/wenci/p/10432932.html (两个字符串求最长公共子串的长度)

既然知道了两个串的最长公共子串怎么求

那我们延伸一下,考虑两个变量,maxx表示在当前拿上来匹配得这个串在每个节点为终点时最长匹配的长度

minn表示在之前所有串上匹配完,到当前节点最长匹配的长度

先解释一下拓扑序的基数排序

inline void radix_sort(){
int i,j,k;
for(i=;i<=tot;i++){
tong[node[i].len]++;
}//开桶记录长度
for(i=;i<=tot;i++){
tong[i]+=tong[i-];
}//表示当前长度能排到多少名
for(i=;i<=tot;i++){
id[tong[node[i].len]--]=i;//重新排序后的数值
}
}

每一个串重新匹配的操作

inline bool work(){
if(scanf("%s",s)==EOF) return false;
int p=,len=;int i,j,k;
for(i=;i<=tot;i++){
node[i].maxx=;
}//把当前串的最大匹配清零
int l1=strlen(s);
for(i=;i<l1;i++){
int now=s[i]-'a'+;
if(node[p].ch[now]){
p=node[p].ch[now];len++;
}
else{
while(p&&!node[p].ch[now]){
p=node[p].fa;
}
if(!p){
p=;len=;
}
else{
len=node[p].len+;p=node[p].ch[now];
}
}//以上都和两个串匹配操作一样
node[p].maxx=max(node[p].maxx,len);//这里更新一下当前串的最大匹配
}
for(i=tot;i;i--){//按照倒拓扑序,要优先修改儿子节点更新父亲节点
int t=id[i];//基数排序后的序号
node[t].minn=min(node[t].minn,node[t].maxx);//更新当前节点的最大匹配
if(node[t].maxx>=node[t].len&&node[t].fa){//如果当前节点是满匹配的,那么删去结尾最后一个,也是满匹配的
node[node[t].fa].maxx=node[node[t].fa].len;//把父亲节点的匹配也更新了
}
}
return true;
}

最后贴整篇代码

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
inline int read(){
int w=,f=;
char ch=getchar();
while(ch<''||ch>''){
if(ch=='-') f=-;
ch=getchar();
}
while(ch>=''&&ch<=''){
w=(w<<)+(w<<)+ch-;
ch=getchar();
}
return w*f;
}
int n,m,lst=,tot=;
long long size[],sum[];
struct Node{
int ch[],len,fa,maxx,minn;
}node[];
bool flag;
inline void extend(int now){
int p=lst;tot++;lst=tot;int np=tot;
node[np].len=node[p].len+;
while(p&&!node[p].ch[now]){
node[p].ch[now]=np;
p=node[p].fa;
}
if(!p) node[np].fa = ;
else{
int q = node[p].ch[now];
if(node[q].len == node[p].len + ){
node[np].fa = q;
}
else{
int nq=++tot;node[nq]=node[q];
node[nq].len=node[p].len+;
node[np].fa=node[q].fa=nq;
while(p&&node[p].ch[now] == q){
node[p].ch[now]=nq;
p=node[p].fa;
}
}
}
}
int tong[],id[],ans;
char s[];
inline void radix_sort(){
int i,j,k;
for(i=;i<=tot;i++){
tong[node[i].len]++;
}
for(i=;i<=tot;i++){
tong[i]+=tong[i-];
}
for(i=;i<=tot;i++){
id[tong[node[i].len]--]=i;
}
}
inline bool work(){
if(scanf("%s",s)==EOF) return false;
int p=,len=;int i,j,k;
for(i=;i<=tot;i++){
node[i].maxx=;
}
int l1=strlen(s);
for(i=;i<l1;i++){
int now=s[i]-'a'+;
if(node[p].ch[now]){
p=node[p].ch[now];len++;
}
else{
while(p&&!node[p].ch[now]){
p=node[p].fa;
}
if(!p){
p=;len=;
}
else{
len=node[p].len+;p=node[p].ch[now];
}
}
node[p].maxx=max(node[p].maxx,len);
}
for(i=tot;i;i--){
int t=id[i];
node[t].minn=min(node[t].minn,node[t].maxx);
if(node[t].maxx>=node[t].len&&node[t].fa){
node[node[t].fa].maxx=node[node[t].fa].len;
}
}
return true;
}
int main(){
scanf("%s",s);int i,j,k;
int l=strlen(s);
for(i=;i<=l;i++){
extend(s[i]-'a'+);
}
radix_sort();
for(i=;i<=tot;i++){
node[i].minn=node[i].len;
}
while(work());
for(i=;i<=tot;i++){
ans=max(ans,node[i].minn);
}
cout<<ans<<endl;
return ;
}

最长公共子串2(LCS2) lg SP1812的更多相关文章

  1. 多个串的最长公共子串 SPOJ - LCS2 后缀自动机

    题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...

  2. SPOJ LCS2 多个串的最长公共子串

    这里串最多有10个,找所有串的最长公共子串 这里后缀自动机做,以第一个串建立后缀自动机,后面的串一个个去匹配,每次得到当前串在可到达状态上所能得到的最长后缀长度 拿所有串匹配后得到的结果进行计算 #i ...

  3. 最长公共子串(LCS) lg SP1811

    后缀自动机的一大用处就是求最长公共子串了 这道题的话题意就是给你两个字符串,求最长公共子串 做法的话是先使用一个字符串建立SAM,然后让另一个串在上面进行匹配 匹配的策略是优先匹配当前节点的下一个字符 ...

  4. 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

    出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...

  5. [Data Structure] LCSs——最长公共子序列和最长公共子串

    1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...

  6. HDU 1503 带回朔路径的最长公共子串

    http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...

  7. 最长公共子序列PK最长公共子串

    1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...

  8. 动态规划(一)——最长公共子序列和最长公共子串

    注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...

  9. 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

    Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...

随机推荐

  1. linux中网络命令

    write 解释 命令名称:write 命令所在路径:/usr/bin/write 执行权限:所有用户 功能描述:给用户发信息,以Ctrl+D保存结束 语法 write <用户名> 示例 ...

  2. 仁和药业顺利出局,布局地产万科A

    仁和药业布局到第二单,被止盈了,盈利大约1.1%.这几日地产行业回调明显,所以布局了万科A. 资金量W11.8 建仓价格28.6 加仓系数1.5 加仓间隔2.70% 总盈利比6.50% 期待吧!

  3. (转)elasticsearch collapse 折叠字段应用

    转自:https://elasticsearch.cn/article/132 在 Elasticsearch 5.x 有一个字段折叠(Field Collapsing,#22337)的功能非常有意思 ...

  4. Github无法访问的解决办法

    #github 192.30.253.113 github.com 192.30.253.113 github.com 192.30.253.118 gist.github.com 192.30.25 ...

  5. java面向对象入门(1)-入门介绍

    在本 Java OOPs 概念教程中,我们将学习四种主要的面向对象原则 -- 抽象.封装.继承和多态性.它们也被称为面向对象编程范式的四大支柱. _抽象_是在不考虑无关细节的情况下公开实体基本细节的过 ...

  6. day 17 初始递归

    递归函数 了解什么是递归 : 在函数中调用自身函数 最大递归深度默认是997/998 —— 是python从内存角度出发做的限制 能看懂递归 能知道递归的应用场景 初识递归 —— 算法 —— 二分查找 ...

  7. CF #621 div.2

    三连否认跪了 T1 开了第一题水题,一遍交过 /* make by ltao */ #include <iostream> #include <cstdio> #include ...

  8. C#MVC用ZXing.Net生成二维码/条形码

    开篇:zxing.net是.net平台下编解条形码和二维码的工具. 首先创建新项目 选择MVC模板  添加一个控制器  在项目引用中的引用ZXing 进行联网下载 控制器需要引用 后台控制器   pu ...

  9. 【Thread】java线程之对象锁、类锁、线程安全

    说明: 1.个人技术也不咋滴.也没在项目中写过线程,以下全是根据自己的理解写的.所以,仅供参考及希望指出不同的观点. 2.其实想把代码的github贴出来,但还是推荐在初学的您多亲自写一下,就没贴出来 ...

  10. so the first day

    welcome to the world it sucks but you gona love it