首页 > 编程语言 >KMP算法

KMP算法

时间:2023-07-08 20:44:08浏览次数:37  
标签:AB 后缀 kmp int 算法 KMP 文本 模板

一.引入(洛谷 P3375)

给出两个字符串 \(s_1\) 和 \(s_2\),若 \(s_1\) 的区间 \([l, r]\) 子串与 \(s_2\) 完全相同,则称 \(s_2\) 在 \(s_1\) 中出现了,其出现位置为 \(l\)。
现在请你求出 \(s_2\) 在 \(s_1\) 中所有出现的位置。
\(s1\)称为文本串,\(s2\)称为模板链

二.简陋版本

不难想到,用两个\(for\)一个位置一个位置比对即可,复杂度为\(O(n*m)\)

三.KMP算法

为了省去那些无谓的比对,KMP算法应运而生。

1.最长相等前后缀

例如\(ABBABB\),其最长相等前后缀就是\(ABB\)

2.核心思想

在安位比对之后,若遇到此位模板串和文本串不同时,可以通过最长相等前后缀将模板串的头拉到当前位置,如

       
文本串:abcacababcab
模板串:abcab(调整前)
模板串:   abcab(调整后)

对于第五个位置两者不一样,对于\(abca\),最长相等前后缀是\(a\),于是将模板串调整到相应位置,省去了很多比较

3.正确性

如此比较我们不会漏掉任何一个答案,任何答案不会藏在调整前和调整后中间的状态,下面用反证法证明:

如下特殊形式,X代表此位二者不同,只有遇到不同位时才需要调整,意味着X以前全一样
文本串:AB ··· AB ··· AB ···
              1      2
模板串:AB ··· AB ··· AB X···
              3      4
比对到X位置时,我们开始调整,如果说此时最长相等前后缀为AB,则正确情况为:
文本串:AB ··· AB ··· AB ···
模板串:              AB ··· AB ··· AB X···
如果我们在中间有遗漏可能匹配成功,即如下情况可能成功:
文本串:AB ··· AB ··· AB ···
              5      6
模板串:       AB ··· AB ··· AB X···
              7      8      9
1~2与3~4一样,若上述情况成功匹配,则5~6与7~8相同,则7~8与8~9相同,最长相等前后缀应为7~8,与上文所说AB相矛盾,得证

四.代码讲解

这种感觉更像是抽动模板串的操作

1.\(kmp[N]\)

\(kmp[k]\)代表对于1~\(k\)这段的最长相等前后缀长度

2.匹配

	j=0;//理解为目前模板串比较到哪一位了
	for(int i=1;i<=l1;i++)
	{
		while(j&&s1[i]!=s2[j+1])//若j=0但s1[i]==s2[j+1]不就死循环了吗
		                        //循环找到可能成功的情况,都s1[i]!=s2[j+1]了
		                        //肯定不会成功啊
			j=kmp[j];//模板串调整到kmp[j]位置,再安放到对应文本串位置
		if(s1[i]==s2[j+1])
			j++;//模板链继续向后拓展
		if(j==l2)//匹配成功
		{
			cout<<i-l2+1<<endl;
			j=kmp[j];//继续新一轮匹配,可能多解
		}
	}

3.\(kmp[N]\)求解

\(kmp[0]=kmp[1]=0\),因为前缀后缀都不包括自身
考虑将模板串与自身比对,如:

文本串:ABABAC
模板串:  ABABAC
对于不同的C-B,即第六位,ABA刚好就是前五位构成串的最长相等前后缀,很好理解
int j=0;
for(int i=2;i<=l2;i++)
	{
		while(j&&s2[i]!=s2[j+1])
			j=kmp[j];
		if(s2[i]==s2[j+1])
			j++;
		kmp[i]=j;
	}

4.AC代码

#include<bits/stdc++.h>
using namespace std;
const int  N=1e6+10;
int kmp[N],l1,l2,j;
char s1[N],s2[N];
int main()
{
	scanf("%s",s1+1);
	scanf("%s",s2+1);
	l1=strlen(s1+1);
	l2=strlen(s2+1);
	for(int i=2;i<=l2;i++)
	{
		while(j&&s2[i]!=s2[j+1])
			j=kmp[j];
		if(s2[i]==s2[j+1])
			j++;
		kmp[i]=j;
	}
	j=0;
	for(int i=1;i<=l1;i++)
	{
		while(j&&s1[i]!=s2[j+1])
			j=kmp[j];
		if(s1[i]==s2[j+1])
			j++;
		if(j==l2)
		{
			cout<<i-l2+1<<endl;
			j=kmp[j];
		}
	}
	for(int i=1;i<=l2;i++)
		cout<<kmp[i]<<" ";
	return 0;
}

5.时间复杂度

\(O(N+M)\),看不懂咋证的,逃(

标签:AB,后缀,kmp,int,算法,KMP,文本,模板
From: https://www.cnblogs.com/kezhuo/p/17537826.html

相关文章

  • Pollard-Rho 分解算法学习笔记
    Pollard-Rho分解算法Pollard-Rho算法是一种用于快速找到\(n\)的一个非平凡约数的方法。生日悖论在不少于\(23\)个人中至少有两人生日相同的概率已经大于\(50\%\)。更一般的形式,随机选取在\(\left[1,N\right]\)范围内的整数,期望到第\(O(\sqrt{N})\)个出现重复。用下面的方......
  • 阵列信号处理及matlab仿真-------波束形成算法基础知识以及MMSE、MSNR和LCMV的MATLAB
    上一篇《阵列信号处理及MATLAB仿真-----阵列信号绪论》里面说了阵列信号处理研究的四个主要问题:波束形成技术、空间谱估计、信号源定位、信源分离。接下来我们就波束形成来做一个详细的学习。一、波束形成的定义:首先说一下它的物理意义,阵列天线的方向图是全方向的,但是......
  • 网络2️⃣HTTPS-密钥交换算法
    SSL/TLSHTTPS是在TCP和HTTP之间添加SSL/TLS安全协议,解决HTTP的安全性问题。在HTTP中,通信之前需要进行TLS握手。密钥交换算法:不同密钥交换算法的TLS握手流程不同。RSA:简单,但存在前向安全问题(如果服务端私钥泄漏,过去被第三方截获的所有TLS通讯密文都会被......
  • 【算法】根据二叉树的级别返回排序后的元素列表
    根据给定的Node树节点,返回包含按级别排序的树中元素的列表,这意味着根元素位于第一位,然后根子元素(从左到右)位于第二位和第三位,依此类推。1publicclassNode2{3publicNodeLeft;4publicNodeRight;5publicintValue;67publicNode(No......
  • 手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实
    手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实体识别、CypherCheetsheet详细教学等效果预览:1.知识图谱存储方式知识图谱存储方式主要包含资源描述框架(ResourceDescriptionFramework,RDF)和图数据库(GraphDatabase)。1.1资源描述框......
  • 42. 查找算法
    一、线性查找算法  线性查找是逐一比对,发现有相同值,就返回下标,否则返回-1。这里,我们实现的线性查找是找到一个满足条件的值就返回。/***@brief线性查找**@paramA待查找的数组*@paramN数组的长度*@paramvalue待查找的元素*@returnint如果找到返回......
  • KMP
    烤馍片是一种算法,这种算法我忘了就学,学了就忘,所以这里再写一遍加深印象(KMP这个东西呢它可以在\(O(n+m)\)的时间复杂度内完成字符串的匹配,虽然但是我用字符串哈希我做匹配不也一个道理吗?KMP可以与处理出来一个叫\(fail\)的数组(也可以叫\(next\)),可以完成很多很厉害的东西。......
  • 游戏AI-寻路-A*寻路算法
    算法介绍:作用:在一个图中,提供一个起点A与一个终点B,给你找出一条估算出来较短的路时间复杂度:n*log(m),n表示图中的节点数,m表示总边的数量时间复杂度分析:一般游戏中的图是一个二维矩阵,所以每个点的方向也就上下左右这么几个,所以每个点枚举方向的时间为常数虽然复杂度为:n*lo......
  • 数据结构与算法(一)
    需要点Java编程基础常见的数据结构栈(Stack):栈是一种特殊的线性表,它只能在一个表的一个固定端进行数据结点的插入和删除操作。队列(Queue):队列和栈类似,也是一种特殊的线性表。和栈不同的是,队列只允许在表的一端进行插入操作,而在另一端进行删除操作。数组(Array):数组是一种聚合数据......
  • C/C++数据结构与算法课程设计[2023-07-06]
    C/C++数据结构与算法课程设计[2023-07-06]数据结构与算法课程设计一、课程设计的目的、要求和任务 本课程设计是为了配合《数据结构与算法》课程的开设,通过设计完整的程序,使学生掌握数据结构的应用、算法的编写等基本方法。1.课程的目的(1)使学生进一步理解和掌握课堂上所学......