题意: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. 展讯sprd_battery.c 充电驱动

    sprd_battery.c 是充电驱动,这个是充电功能的核心内容,电量显示策略.温度检测策略.充电保护机制等功能在这里实现,功能实现与硬件细节剥离,调用通用接口实现逻辑控制: 1 sprdbat_p ...

  2. gcd手写代码及STL中的使用方法

    一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...

  3. python基础入门之三 —— 字符串

    1.格式 一对引号和三对引号可以表示字符串 (三引号保留换行) 2.下标 从0开始循序向下分配 str1='abcdefg' print(str1) print(str1[0]) print(str1 ...

  4. 部署基于Gitlab+Docker+Rancher+Harbor的前端项目这一篇就够了

    部署基于Gitlab+Docker+Rancher+Harbor的前端项目这一篇就够了 安大虎 ​ momenta 中台开发工程师 6 人赞同了该文章 就目前的形势看,一家公司的运维体系不承载在 Do ...

  5. 0.96寸OLED显示屏驱动手册(SSD1306)

    MCU IIC接口 IIC通信接口由从地址位SA0,IIC总线数据信号SDA(输出SDAout/D2和输入SDAin /D1)和IIC总线时钟信号SCL(D0).不管是数据线还是时钟线都需要连接上拉电 ...

  6. layui弹出表单提交后,界面model验证部分起作用

    情况1----input属性中type=submit时验证都可以起作用,但是弹出层表单的返回值不能获取,所以用ajax二次提交后会出现重复添加数据的问题 情况2----input属性中type=but ...

  7. Jacoco收集单元测试、集成测试和系统功能测试覆盖率

    Jacoco收集单元测试.集成测试和系统功能测试覆盖率 2020-02-27  目录 1 安装版本2 被测系统代码示例3 收集单元测试覆盖率4 收集集成和功能测试覆盖率 代码覆盖率可在单元测试.系统测 ...

  8. [P5748] 集合划分计数 - 生成函数,NTT

    求 \(10^5\) 以内的所有贝尔数:将 \(n\) 个有标号的球划分为若干非空集合的方案数 Solution 非空集合的指数生成函数为 \(F(x)=e^x-1\) 枚举一共用多少个集合,答案就是 ...

  9. Java锁机制深入理解

    Java锁机制 背景知识 指令流水线 ​ CPU的基本工作是执行存储的指令序列,即程序.程序的执行过程实际上是不断地取出指令.分析指令.执行指令的过程. ​ 几乎所有的冯•诺伊曼型计算机的CPU,其工 ...

  10. Web简单小结

    一.HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应:<h1 onclick="this.innerHTML='你点我干啥'">请点击这里& ...