最长公共子串2(LCS2) lg SP1812
题意: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的更多相关文章
- 多个串的最长公共子串 SPOJ - LCS2 后缀自动机
题意: 求多个串的最长公共子串 这里用的是O(n)的后缀自动机写法 我后缀数组的专题有nlog(n)写法的 题解: 对于其中的一个串建立后缀自动机 然后对于后缀自动机上面的每一个节点求出每一个节点最长 ...
- SPOJ LCS2 多个串的最长公共子串
这里串最多有10个,找所有串的最长公共子串 这里后缀自动机做,以第一个串建立后缀自动机,后面的串一个个去匹配,每次得到当前串在可到达状态上所能得到的最长后缀长度 拿所有串匹配后得到的结果进行计算 #i ...
- 最长公共子串(LCS) lg SP1811
后缀自动机的一大用处就是求最长公共子串了 这道题的话题意就是给你两个字符串,求最长公共子串 做法的话是先使用一个字符串建立SAM,然后让另一个串在上面进行匹配 匹配的策略是优先匹配当前节点的下一个字符 ...
- 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
出处 http://segmentfault.com/blog/exploring/ 本章讲解:1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度:2. 与之类似但不同的 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- HDU 1503 带回朔路径的最长公共子串
http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...
- 最长公共子序列PK最长公共子串
1.先科普下最长公共子序列 & 最长公共子串的区别: 找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的.而最长公共子序列则并不要求连续. (1)递归方法求最长公共子序列的长度 1) ...
- 动态规划(一)——最长公共子序列和最长公共子串
注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...
- 字符串hash + 二分答案 - 求最长公共子串 --- poj 2774
Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在 ...
随机推荐
- css3基本选择器+属性选择器+动态伪类+UI状态伪类+结构类
后代选择器 祖先元素 后代元素{ } 子元素选择器(直接子元素选择器) 父元素>子元素{ } 兄弟选择器 元素+兄弟元素(紧邻该元素之后的下一个兄弟元素) 所有兄弟元素选择器 元素~兄弟元素(该 ...
- cisco 路由器的操作系统基础命令集
路由器和交换机里都有操作系统,cisco的操作系统叫ios. 怪不得路由器贵,原来也是带操作系统的机器啊,以前真是小白. ios里的几种模式 1,>:用户模式:啥也干不了. 2,#:特权模式:用 ...
- 第1章.Collections类、泛型类和Timing类概述
1.1 群集(collection)的定义 群集是一种结构化的数据类型.它存储数据,并且提供数据的添加.删除.更新操作,以及对群集的不同属性值的设置与返回操作. 群集可以分为两类:线性的和非线性的. ...
- maven的核心概念——仓库
第十章仓库 10.1 分类 [1]本地仓库:为当前本机电脑上的所有Maven工程服务. [2]远程仓库 (1)私服:架设在当前局域网环境下,为当前局域网范围内的所有Maven工程服务. (2)中央仓库 ...
- matplotlib制作图表数据
import matplotlib.pyplot as plt import matplotlib fig=plt.figure() labels=['陆地','海洋'] data=[29,71] p ...
- Java代码操作Elasticsearch
创建maven项目,导入依赖 <dependency> <groupId>junit</groupId> <artifactId>junit</a ...
- 电脑和手机上常用apk或Pc软件的重要目录或文件或文件夹路径
常用apk或Pc软件的重要目录或文件或文件夹路径 01.hosts文件位置在哪里 C:\Windows\System32\drivers\etc 02.Windows7的锁屏壁纸目录在哪 C:\Win ...
- SpringBoot2.x-笔记(01)
程序入口 @SpringBootApplication public class SpringbootApplication { public static void main(String[] ar ...
- Minion 主机同步失败问题,全过程
如果出现以下状态 token也有了 这个是salt-api 说明你salt-api没问题 点击同步主机 查看你产品线管理那里,添加了你这个salt-api没? 配置参考文档 https://gith ...
- Docke-ce 安装
Docker-ce 的安装 安装系统工具 yum install -y yum-utils device-mapper-persistent-data lvm2 添加docker镜像源 yum-con ...