首页 > 编程语言 >KMP算法

KMP算法

时间:2024-07-15 22:30:57浏览次数:19  
标签:nxt string KMP substr 算法 ans size

KMP算法

KMP算法是一个字符串算法,通常用于匹配字符串。

KMP算法的原理

如果我们暴力枚举下标 \(i,j\),\(i\) 是文本串的下标,\(j\) 是模式串(你要在文本串中匹配的字符串)的下标,时间复杂度 \(O(NM)\),其中 \(N,M\) 分别为文本串和模式串的长度。

我们看一下匹配过程:(gif 动图请耐心观看)

时间复杂度高吧,出题人随便就 \(hack\) 掉了。

1 2 3 4 5 6 7 8 9 10
文本串 x y x y x y x y x w
模式串 x y x y x y w y

咦?我们会发现 \(文本串.substr(3,4)=模式串.substr(1,4)=模式串.substr(3,4)="xyxy"\),这样我们 \(i=7,j=7\) 匹配失败时可以跳 \(2\) 次(\(j=3\)),就可以达到正确性和时间复杂度平衡的效果。

我们维护 \(nxt_i\) 表示s和s以i结尾的最长公共前后缀的长度,这样我们在 \(文本串_i,模式串_j\) 匹配失败时 \(j\) 可以直接跳到 \(nxt_j\)。

维护 nxt_i

若 \(s_i==s_j\) 也就是 \(模式串_i,模式串_j\) 匹配时,nxt[++i]=++j(其他同理写法也可以,最好固定一个写法),否则按文本串和模式串匹配失败来。

代码

void getNext(string s)//初始化和文本串没关系
{
	nxt[0] = -1;
	int i = 0, j = -1;
	while (i < s.size())
		if (j == -1 || s[i] == s[j])
			nxt[++i] = ++j;
		else
			j = nxt[j];
	return;
}
void KMP(string s, string t)//P3375的询问代码
{
	getNext(t);
	int i = 0, j = 0;
	while (i < s.size())
	{
		if (j == t.size() - 1 && s[i] == t[j])
		{
			cout << i - j + 1 << '\n';
			j = nxt[j];
		}
		if (j == -1 || s[i] == t[j])
			i++, j++;
		else
			j = nxt[j];
	}
	return;
}

KMP算法应用

P3375 【模板】KMP

P4391 [BOI2009] Radio Transmission 无线传输

给你一个字符串 \(s_1\),它是由某个字符串 \(s_2\) 不断自我连接形成的(保证至少重复 \(2\) 次)。但是字符串 \(s_2\) 是不确定的,现在只想知道它的最短长度是多少。

不想说过程,直接说结论:ans = n - nxt[n]

CF1200E Compress Words

cin >> n;
for (int i = 1; i <= n; i++)
{
	cin >> s;
	if (ans.empty())
		ans = s;
	else
	{
		int len = min(s.size(), ans.size());
		string s1 = s.substr(0, len);
		string s2 = ans.substr(ans.size() - len, len);
		string s3 = s1 + "#" + s2;//中间必须拼上"#",不然有可能最长公共前后缀重合。
		getNext(s3);
		ans += s.substr(nxt[s3.size()]);
	}
}
cout << ans;

标签:nxt,string,KMP,substr,算法,ans,size
From: https://www.cnblogs.com/wbw121124/p/18304161

相关文章

  • LeetCode算法笔记5
    题目描述给你一个字符串 s,找到 s 中最长的 回文子串示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:1<=s.length<=1000s 仅由数字和英文字母组成解法:classSolution:deflongestPalindrome(sel......
  • LeetCode算法笔记2
    题目描述给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0 开头。示例1:输入:l1=[2,4,3],l......
  • 【matlab】智能优化算法优化BP神经网络
    目录引言一、BP神经网络简介二、智能优化算法概述三、智能优化算法优化BP神经网络的方法四、蜣螂优化算法案例1、算法来源2、算法描述3、算法性能结果仿真代码实现引言智能优化算法优化BP神经网络是一个重要的研究领域,旨在通过智能算法提高BP神经网络的性能和......
  • 最爽手撕算法个人笔记【第一周-数组】
    27.移除元素给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素。元素的顺序可能发生改变。然后返回nums中与val不同的元素的数量。假设nums中不等于val的元素数量为k,要通过此题,您需要执行以下操作:更改nums数组,使nums的前k个元素包含不......
  • 基于改进K-means的网络数据聚类算法matlab仿真
    1.程序功能描述       K-means属于聚类分析中一种基本的划分方法,常采用误差平方和准则函数作为聚类准则。主要优点是算法简单、快速而且能有效地处理大数据集。研究和分析了聚类算法中的经典K-均值聚类算法,总结出其优点和不足。重点分析了K-均值聚类算法对初始值的依赖性......
  • AcWing 2074:倒计数 ← 双指针算法
    【题目来源】https://www.acwing.com/problem/content/2076/【题目描述】艾弗里有一个由N个正整数构成的数组。数组中的第i个整数是Ai。如果一个连续的子数组的长度为m,并且按顺序包含整数m,m−1,m−2,…,2,1,则称它为m倒计数。例如,[3,2,1]是3倒计数。请帮助艾......
  • 代码随想录算法训练营第六十六天 | Bellman_ford 队列优化算法(SPFA)、Bellman_ford之
    Bellman_ford队列优化算法(SPFA)题目链接:https://kamacoder.com/problempage.php?pid=1152文档讲解:https://programmercarl.com/kamacoder/0094.%E5%9F%8E%E5%B8%82%E9%97%B4%E8%B4%A7%E7%89%A9%E8%BF%90%E8%BE%93I-SPFA.html思路Bellman_ford算法每次松弛都是对所......
  • 代码随想录算法训练营第六十五天 | dijkstra(堆优化版)精讲、Bellman_ford 算法精讲、复
    dijkstra(堆优化版)精讲—卡码网:47.参加科学大会题目链接:https://kamacoder.com/problempage.php?pid=1047文档讲解:https://programmercarl.com/kamacoder/0047.%E5%8F%82%E4%BC%9Adijkstra%E5%A0%86.html思路当节点数多,边数少(稀疏图)时,可以考虑从边的角度出发,用堆来......
  • 【Unity】凸包算法对比及实现
    背景在做闵可夫斯基差的可视化的时候,获得了很多个点,想要知道其是否包含原点,需要连接一个包裹这些点的最小凸多边形。因此就单独研究了这个部分,实现了功能并进行分析对比。凸包算法可以在多个散落的点中找到最小能包裹它的外壳,像套上一个橡皮筋一样。这里主要采用Graham算法进行代......
  • Vue--DIFF 算法
    一、什么是DIFF算法?DIFF算法用于比较两棵虚拟DOM树的差异,从而生成最小化的DOM更新操作。这个过程通常分为以下几个步骤:树形结构的对比:逐层对比新旧虚拟DOM树,找出差异节点。最小化更新:对实际DOM进行最小量的修改,以反映虚拟DOM的变化。二、Vue的DIFF算法原理......