首页 > 其他分享 >KMP

KMP

时间:2023-12-12 19:45:15浏览次数:24  
标签:前缀 pattern 数组 KMP now match

KMP算法实现

KMP串匹配主要分为两个步骤,即获得match数组(或者说next数组),然后应用match数组来进行串匹配的简化

  1. 获取match数组
    KMP的精髓就在于使用match数组使得i指针不需回退,使得暴力的m*n的时间复杂度变为m+n的时间复杂度,其中的m指的就是求match数组的复杂度。

match数组的含义为,当当前字符与主串匹配失败时,我们并不直接整个回退两个指针,而是寻求一个前缀字符串(即从头开始的子串)可以和以该字符串前一个字符为后缀的字串相匹配,使得模式串不需回退到头,而是从该前缀字符的最后一个字符开始匹配

下面是求match数组的代码,主要的思想就是迭代求解。
注意这里的match数组要求下标从0开始

#include <iostream>
#include <string>
using namespace std;
const int N = 1e5 + 20;
int match[N];
string pattern;
string str;
void get_match()
{
	match[0] = -1;//第0个字符显然没有前缀字串,赋值为-1
	for (int i = 0; i < pattern.size(); i++)//遍历模式串的每一个字符,寻找可以与其匹配的模式串
	{
		int now_match = match[i - 1];
		while (now_match > 0 && pattern[now_match + 1] == pattern[i])//当该前缀与后缀不匹配时,递归(迭代?)进行求解,去找一个更小的前缀
			now_match = match[now_match];
		if (pattern[now_match + 1] == pattern[i])//循环退出,若相等则为找到了
			match[i] = now_match + 1;
		else // 不等则没有这样的前缀,赋值为-1
			match[i] = -1;
	}
}

接下来是KMP算法的实现、

void KMP()
{
	int i = 0, j = 0;
	while (i < str.size())//主串还未到头就继续
	{
		if (str[i] == pattern[j])//若当前字符可以匹配,双指针都向后移动一位
		{
			i++;
			j++;
		}
		else if (j > 0)//若匹配不上,尝试移动j寻找match[j - 1] + 1(为防止越界j > 0)
		{
			j = match[j - 1] + 1;
		}
		else//j <= 0 ,说明第一个字符就匹配不上,主串指针向后移动一位
		{
			i++;
		}
		if (j == pattern.size()) // 当匹配长度等于模式串时,匹配成功,输出其起始位置,同时为了匹配下一个可能的模式串,j指针同理移动
		{
			cout << i - j << endl;
			j = match[j - 1] + 1;
		}
			
	}
}

标签:前缀,pattern,数组,KMP,now,match
From: https://www.cnblogs.com/CrescentWind/p/17897665.html

相关文章

  • KMP算法
    1.暴力匹配暴力匹配算法的步骤如下:遍历主串中的每个可能的起始位置,从第一个字符开始。对于每个起始位置,逐个比较主串和模式串中对应位置的字符。如果发现不匹配的字符,即主串和模式串中对应位置的字符不相等,将模式串向右移动一个位置,继续比较。如果模式串完全匹配主串中的一......
  • KMP
    简介KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。实现构造next[]数组前缀:除最后一个字符外,......
  • 关于kmp模板
    那个求p串的next数组这个版本是下标从1开始的字符串,如果从0开始的话,可以在前面加空字符,然后p.size或者s.size的地方-1即可。nex[1]=0    for(inti=2,j=0;i<=p.size();i++){if(j&&p[i]!=p[j+1])j=nex[j];if(p[i]==p[j+1])j++;nex[i]=j;} kmp函数......
  • AcWing 831. KMP字符串
    题面:给定一个字符串S,以及一个模式串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串P在字符串S中多次作为子串出现。求出模式串P在字符串S中所有出现的位置的起始下标。原题链接:831.KMP字符串-AcWing核心:next数组-最长相等前后缀next[i]存储......
  • KMP字符串匹配算法 整理
    KMP整理题面视频详解KMP的作用KMP算法的主要作用是求出一个字符串(模式串)是否为另一个字符串(主串)的子串,并同时求出它出现的位置,也即字符串匹配问题。算法解析暴力先说暴力算法:从头开始枚举模式串位置的起点,然后遍历从起点往后\(m\)个字符,检查它是否与模式串完全相同......
  • KMP
    一、算法描述本篇文章水平不够,讲不清楚KMP到底是怎么回事,以后再更新一下。本篇文章讲述的是KMP算法,一个著名的字符串匹配算法,效率很高,\(O(n)\)的时间复杂度。难点在于:如何理解\(next[i]\)★★★\(ne[i]=j\)表示,\(p[1~j]=p[i-j+1,i]\),从\(1\)到\(j\)的前缀......
  • P3375 【模板】KMP( 普及/提高− ) 题解
    题目传送门思路:首先我们要学习一下\(KMP\)算法,不会的可以看这个大佬的文章那么我们就直接开始讲思路了。针对于每一位,\(kmp\)算法已经预处理出了一个对应\(kmp\)数组的单元,映射着如果此位失配,它可能的最靠后的一个重新开头是哪一个。让我们举一个例子:假如让\(aaab\)与......
  • KMP算法
    #include<iostream>usingnamespacestd;int*getNext(stringpattern){int*next=(int*)malloc(sizeof(int)*pattern.size());if(next==NULL){returnNULL;}next[0]=-1;intj=-1;for(inti=1;i<p......
  • KMP板子
    updateon2023.11.17NOIP前来复习板子,发现KMP整理的不是很到位,所以更新详细一些。模板题抽象的blog浅显易懂的讲解视频:(dalao讲得太好了\(%%%\))备用网址\(kmp\)(字符串匹配)的概念:主串:被匹配的字符串模式串:匹配的串最长前后缀:一个字符串某个前缀后后缀相同,而且长度尽可......
  • KMP与自动机
    KMP与AC自动机都是字符串匹配KMP是单模匹配ac自动机是多模匹配KMP原理例子当我们匹配字符串A(长度为n)中是否有B(长度为m,m<n)的时候比如:AABCDABCDEFBABCDE一个朴素的思路是暴力,复杂度当然是O(n*m)KMP就是一个优化的算法KMP的理论基础就是,并不是每次匹......