LCS2 - Longest Common Substring II

这篇具有很好参考价值的文章主要介绍了LCS2 - Longest Common Substring II。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

洛谷LCS2 - Longest Common Substring II

题目大意

给你一些字符串,求它们的最长公共子串。

字符串个数不超过 10 10 10,每个字符串的长度不超过 100000 100000 100000


题解

可以先看看LCS - Longest Common Substring。

这题与上面那题类似,只不过要多一些操作。

首先,用第一个字符串建一个 S A M SAM SAM,然后在 S A M SAM SAM上面匹配其他的字符串,匹配的方式见上面这道题。

因为有多个字符串,所以不能只用 n o w now now了。我们用 w [ p ] . m x [ i ] w[p].mx[i] w[p].mx[i]表示在用字符串 i i i来在 S A M SAM SAM上匹配时 S A M SAM SAM的位置 p p p上能够达到的最长的长度。

当然,如果一个点可以被匹配到,则这个点的祖先都可以被匹配到。所以每个点要对其子树取 m a x max max,然后对自己的长度取 m i n min min。这个操作我这边用的是拓扑排序来实现,当然其他方法也可以。

最后,对于 S A M SAM SAM上的每一个位置 p p p,求这个位置在每个字符串匹配后的最小值,即 w [ p ] . m x [ i ] w[p].mx[i] w[p].mx[i]的最小值,让 a n s ans ans对这个值取 m a x max max。最后的 a n s ans ans即为答案。文章来源地址https://www.toymoban.com/news/detail-522399.html

code

#include<bits/stdc++.h>
using namespace std;
const int N=100000;
int s1,t1,cnt,siz=0,lst=0,ans=0,ct[N*2+5],r[N*2+5];
char s[N+5],t[N+5];
queue<int>q;
struct node{
	int len,link,bz,mx[15];
	map<char,int>nxt;
}w[N*2+5];
void add(char c){
	int cur=++siz;
	w[cur].len=w[lst].len+1;
	int p;
	for(p=lst;p!=-1&&!w[p].nxt.count(c);p=w[p].link)
	w[p].nxt[c]=cur;
	if(p==-1) w[cur].link=0;
	else{
		int q=w[p].nxt[c];
		if(w[p].len+1==w[q].len) w[cur].link=q;
		else{
			int cl=++siz;
			w[cl].len=w[p].len+1;
			w[cl].link=w[q].link;
			w[cl].nxt=w[q].nxt;
			for(;p!=-1&&w[p].nxt[c]==q;p=w[p].link)
			w[p].nxt[c]=cl;
			w[q].link=w[cur].link=cl;
		}
	}
	lst=cur;
}
void find(){
	int p=0,now=0;
	for(int i=1;i<=t1;i++){
		char c=t[i];
		if(w[p].nxt.count(c)){
			p=w[p].nxt[c];++now;
		}
		else{
			for(;p!=-1&&!w[p].nxt.count(c);p=w[p].link);
			if(p!=-1){
				now=w[p].len+1;
				p=w[p].nxt[c];
			}
			else{
				now=0;p=0;
			}
		}
		w[p].mx[cnt]=max(w[p].mx[cnt],now);
	}
}
void gt(){
	for(int i=1;i<=siz;i++) ++ct[w[i].link];
	for(int i=1;i<=siz;i++){
		if(!ct[i]) q.push(i);
	}
	while(!q.empty()){
		int u=q.front();q.pop();
		r[++r[0]]=u;
		--ct[w[u].link];
		if(!ct[w[u].link]) q.push(w[u].link);
	}
}
void up(int c){
	for(int i=1;i<=siz;i++){
		int u=r[i];
		w[w[u].link].mx[c]=min(max(w[w[u].link].mx[c],w[u].mx[c]),w[w[u].link].len);
	}
}
int main()
{
	scanf("%s",s+1);
	s1=strlen(s+1);
	w[0].link=-1;
	for(int i=1;i<=s1;i++) add(s[i]);
	gt();
	while(scanf("%s",t+1)!=EOF){
		t1=strlen(t+1);
		++cnt;
		find();
		up(cnt);
	}
	for(int i=1,now;i<=siz;i++){
		now=1e9;
		for(int j=1;j<=cnt;j++){
			now=min(now,w[i].mx[j]);
		}
		ans=max(ans,now);
	}
	printf("%d",ans);
	return 0;
}

到了这里,关于LCS2 - Longest Common Substring II的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 力扣第92题——反转链表 II(C语言题解)

    给你单链表的头指针  head  和两个整数  left  和  right  ,其中  left = right  。请你反转从位置  left  到位置  right  的链表节点,返回  反转后的链表  。 示例 1: 示例 2: 提示: 链表中节点数目为  n 1 = n = 500 -500 = Node.val = 500 1 = left = right = n 我们以下图中黄色区域的链

    2024年01月23日
    浏览(32)
  • 【题解】删除有序链表中重复的元素-I、II

    题目链接:删除有序链表中重复的元素-I 解题思路1:利用set 遍历链表,将元素放入set中,利用set中元素不重复的特点,相当于重复元素只保留了一份,最后再遍历set,重构删除重复元素后的链表 代码如下: 解题思路2:遍历 如果下一个节点的值和本节点的值相同话,当前节

    2024年02月14日
    浏览(31)
  • Golang | Leetcode Golang题解之第45题跳跃游戏II

    题目: 题解:

    2024年04月25日
    浏览(48)
  • 【力扣 445】两数相加 II C++题解(链表+模拟+数学+头插法)

    给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 示例1: 输入:l1 = [7,2,4,3], l2 = [5,6,4] 输出:[7,8,0,7] 示例2: 输入:l

    2024年01月24日
    浏览(31)
  • LeetCode算法题解(回溯)|39. 组合总和、40. 组合总和 II、131. 分割回文串

    题目链接:39. 组合总和 题目描述: 给你一个  无重复元素  的整数数组  candidates  和一个目标整数  target  ,找出  candidates  中可以使数字和为目标数  target  的 所有   不同组合  ,并以列表形式返回。你可以按  任意顺序  返回这些组合。 candidates  中的  同一个  数

    2024年02月05日
    浏览(48)
  • LeetCode算法题解(动态规划)|LeetCoed62. 不同路径、LeetCode63. 不同路径 II

    题目链接:62. 不同路径 题目描述: 一个机器人位于一个  m x n   网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例 1: 示例 2:

    2024年02月05日
    浏览(42)
  • 【动态规划】 LIC&LCS

    前段时间再次复习并加深了 LIS 和 LCS 的内容,于是便来写一篇总结。 首先当然是 O ( n 2 ) O(n^2) O ( n 2 ) 的做法。直接把代码放在这里。 最长上升子序列: 最长公共子序列: 对于 O ( n 2 ) O(n^2) O ( n 2 ) 的做法就不再赘述了。 O ( n 2 ) O(n^2) O ( n 2 ) 的做法时空复杂度都太高了,所

    2024年01月17日
    浏览(26)
  • 【算法】力扣【动态规划,LCS】1143. 最长公共子序列

    1143. 最长公共子序列 本文是对 LCS 这一 动态规划 模型的整理,以力扣平台上的算法题1143:最长公共子序列为模板题进行解析。 该题目要求计算两个字符串的最长公共子序列(Longest Common Subsequence,简称LCS)的长度。字符串的子序列是指在不改变字符顺序的情况下,通过删去

    2024年01月17日
    浏览(47)
  • 687. Longest Univalue Path

    687. Longest Univalue Path l,r别写错

    2024年01月19日
    浏览(36)
  • [动态规划]——线性DP(LIS/LCS/LCIS等) 详解

    线性DP,是较常见的一类动态规划问题,其是在线性结构上进行状态转移,这类问题不像背包问题、区间DP等有固定的模板 线性动态规划的目标函数为特定变量的线性函数,约束是这些变量的线性不等式或等式,目的是求目标函数的最大值或最小值 因此,除了少量问题(如:

    2024年02月10日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包