最长公共子串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: 前面在 ...
随机推荐
- GitLab Runner
GitLab Runner是一个开源项目,用于运行你的作业(jobs)并将结果发送回GitLab.它与GitLab CI结合使用,GitLab CI是GitLab用于协调jobs的开源持续集成服务. ...
- 使用PropTypes进行类型检查
原文地址 1.组件特殊属性——propTypes 对Component设置propTypes属性,可以为Component的props属性进行类型检查. import PropTypes from ' ...
- PHP0023:PHP 相册管理案例
- java循环语句 总结笔记
1.for 循环语句 语法:for(initialization;condition;iteration) public class A { public static void main(Strin ...
- IDEA 代码量统计(Statistic)
IDEA 代码量统计(Statistic) 1.1 前言 项目到了一定阶段,都会想要看看项目的代码量情况,这里主要使用插件Statistic进行代码统计查看. 1.2 安装插件步骤 找到插件市场入口并 ...
- 版本管理git
Git 是目前世界上最先进的分布式版本控制系统. git的主要操作步骤 git.init 初始化,显示成功后去相应的文件夹中查看是不是多了一个git文(版本库) 命令1. git confi ...
- Java学习之String、StringBuffer、StringBuilder
String 我们知道字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多.JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池 ...
- css flex弹性布局学习总结
一.简要介绍 flex( flexible box:弹性布局盒模型),是2009年w3c提出的一种可以简洁.快速弹性布局的属性. 主要思想是给予容器控制内部元素高度和宽度的能力.目前已得到以下浏览器支 ...
- C# WPF简况(2/3)
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF简况(2/3) 阅读导航 本文背景 代码实现 本文参考 1.本文背景 承接上文(C ...
- 两分支部署Hexo
最近把原本部署在GitHub上的hexo同时部署到码云上,速度快到飞起. 可做对比,我的GitHub Pages像乌龟一样慢吞吞,我的Gitee Pages像兔子一样敏捷. 使用hexo,如果换了电脑 ...