首页 > 编程语言 >KMP算法

KMP算法

时间:2024-08-04 22:17:01浏览次数:12  
标签:nxt 前缀 后缀 适配 int 算法 KMP

写在前面

喜报:听了四遍都没学懂的KMP算法,终于在 gyy 大佬的耐心讲解下搞懂了,大佬orz!!!

正文

kmp算法本质上就是对模式串(要匹配的子串 两个串中短的那个 )中很多重复的前缀和后缀索引起来,使得在一个地方失配了也不要紧,不用重新来的算法(看不懂不要紧)

下面我们就来详细介绍一下kmp的几个操作


预处理

a b a b c

用 \(nxt[i]\) 来存储对于模式串1~i中的最长前缀和后缀相等的长度
例如

a b a b c

在 \(i=3\) 时 前缀 \(a\) 等于后缀 \(a\) 所以 \(nxt[3]=1\)
在 \(i=4\) 时 前缀 \(ab\) 等于后缀 \(ab\) 所以 \(nxt[4]=2\)
而在 在 \(i=5\) 时 前缀没有等于后缀所以 \(nxt[5]=0\)
你会发现一个问题,其实 \(nxt[i]\) 就是 \(i\) 上一次在模式串出现的位置(那干嘛不叫 last 呢)
那聪明的你一定会问:这个是用来干嘛的呢?
别急,让我们来看适配操作

适配

a b a b e ...
a b a b c

我们用 \(i\) 来表示文本串(被适配的串)的下标,\(j\) 来表示模式串的下标
我们先一项一项的配,当配到 \(j=5\) 时就发现两个串失配了,那怎么办,前面是不是白配了呢?
别担心,你会发现 \(j=5\) 的前一项 \(j=4\) 其实是适配的,于是就联想到我的 \(nxt[4]==2\) 其实如果和此时的 \(i=4\) 来配也是可以适配的,因为在第 \(j\) 项长度为 \(nxt[j]\) 前缀和后缀是相等的
所以我就将 \(j=nxt[j]\) 第 \(j+1\) 项也适配为止,然后就大功告成了!

提示

其实预处理 \(nxt[j]\) 数组就相当于模式串自身匹配,几乎和适配操作一样,不多赘述

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char a[N],b[N];
int nxt[N];
int main(){
	cin>>a+1>>b+1;
	int la=strlen(a+1),lb=strlen(b+1);
	for(int i=1,j=0;i<=lb;i++){
		while(j&&b[i+1]!=b[j+1])  j=nxt[j]; //如果i+1失配则找到i的上一个相同配子 
		if(b[i+1]==b[j+1])  j++;
		nxt[i+1]=j;
	}
	for(int i=0,j=0;i<=la;i++){
		while(j&&a[i+1]!=b[j+1])  j=nxt[j];
		if(a[i+1]==b[j+1])  j++;
		if(j==lb){
			printf("%d\n",i-lb+2);
		}
	}
	for(int i=1;i<=lb;i++){
		printf("%d ",nxt[i]);
	}
}

标签:nxt,前缀,后缀,适配,int,算法,KMP
From: https://www.cnblogs.com/zcxnb/p/18342310

相关文章

  • KMP学习笔记
    KMP一种字符串单模匹配算法。原理当模式串\(s\)与文本串\(t\)进行匹配时,容易想到的一种朴素做法就是将模式串的第一位与文本串的每一位进行试配。但是这样效率过低,容易被数据卡成\(O(n^2)\)。KMP单模匹配算法引入了一个失配数组border。定义一个字符串的border为一......
  • 【秋招笔试】2024-08-03-科大讯飞秋招笔试题(算法岗)-三语言题解(CPP/Python/Java)
    ......
  • 数据结构:链表经典算法OJ题
    目录前言一、移除链表元素二、反转链表三、合并两个有序链表四、链表的中间节点五、环形链表的约瑟夫问题前言  在了解了链表的相关知识后,我们还需要一些题目进行练习加深对链表这方面知识的理解,也可以用来检测链表这块学的的怎么样,废话不多说,开始上手。一、移......
  • 算法【构建前缀信息解决子数组问题】
    本文需要对掌握哈希表的用法。构建某个前缀信息比如最早出现、最晚出现、出现次数等,是很常见的技巧。除此之外,还有很多种类的前缀信息可以构建出来,解决很多子数组相关问题。下面通过几个题目加深对构建前缀信息这个方法的理解。题目一简要描述:构建前缀和数组。快速解决子......
  • 算法【前缀树】
    注意:学习本篇最少应知道什么是树结构和哈希表怎么用。前缀树又叫字典树,英文名trie。每个样本都从头节点开始根据前缀字符或者前缀数字建出来的一棵大树,就是前缀树。没有路就新建节点;已经有路了,就复用节点。前缀树的使用场景:需要根据前缀信息来查询的场景前缀树的优点:根......
  • 2024“钉耙编程”中国大学生算法设计超级联赛(4)
    题面:https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E9%9D%A2.pdf题解:https://files.cnblogs.com/files/clrs97/%E7%AC%AC%E5%9B%9B%E5%9C%BA%E9%A2%98%E8%A7%A3.pdf Code:A.超维攻坚#include<cstdio>constintN=15,inf=~0U>>......
  • 算法题之旋转链表
    旋转链表给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。示例1:输入:head=[1,2,3,4,5],k=2输出:[4,5,1,2,3]示例2:输入:head=[0,1,2],k=4输出:[2,0,1]提示:链表中节点的数目在范围 [0,500] 内-100<=Node.val<=1000<=k<=......
  • 【机器学习算法基础】(基础机器学习课程)-11-k-means-笔记
        示例案例为了更好地理解K-Means算法,下面通过一个简单的案例进行说明。假设我们有以下10个二维数据点,表示不同商店的销售额(单位:千元)和顾客数(单位:人):[(10,100),(20,80),(30,70),(40,60),(50,50),(60,40),(70,30),(80,20),(90,10),(......
  • KMP 算法学习笔记
    问题引入给出两个字符串\(s1\)和\(s2\),求出\(s2\)在\(s1\)中所有出现的位置(出现指\(s1\)中存在子串与\(s2\)完全相同)。朴素暴力不详细介绍,容易发现时间复杂度不优秀。KMP算法思想在朴素暴力中我们可以发现有很多匹配是不需要再次从头开始重新匹配的,举个例子:ABA......
  • 寻求 Kadane 求连续子数组最大和的算法的优化和验证
    在此处输入图像描述给定一个由N个整数组成的数组A。您希望将数组划分为不相交的连续子数组以使其良好。如果满足以下条件,则认为数组是好的数组:每个元素恰好属于一个子数组。如果我们将每个子数组替换为子数组值的MEX(排除最小值),则生成的数组将按非降序......