首页 > 其他分享 >KMP 字符串匹配 学习笔记

KMP 字符串匹配 学习笔记

时间:2023-08-19 16:56:32浏览次数:26  
标签:dots ch 匹配 int 笔记 KMP 字符串

前言

最近才发现自己写了后缀数组,但并没有其他的字符串算法,今天先把 \(KMP\) 字符串匹配先讲一下。

算法核心

对于字符串匹配,最朴素的方法就是一个字符一个字符地匹配,找到不同的就直接换一个地方匹配。

我们先来看一组样例:
\(ababababe\)

\(ababe\)

对于这组样例,暴力的方法就是直接匹配,从第一位开始匹配,发现从第五个地方开始不一样了,那么我们就直接往后移:
\(ababababe\)

\(\,\,\, ababe\)

发现从第五位开始不一样了,继续往后面移:

\(ababababe\)

\(\quad ababe\)

\(\dots\dots\)

以此类推,我们在第五位发现成功匹配了。

不过这样匹配速度太慢了,复杂度为 \(O(nm)\),然后我们自己直接想肯定不会一个一个的慢慢想,我们在匹配第一个匹配失败后会将模式串(也就是小的那一个)第三第四位直接移到第一第二位(因为他们相同)。那么就可以知道 \(KMP\) 的核心其实就在,每次匹配失败后,将模式串移到相同的地方。

然后就可以想到预处理出一个数组 \(p\),\(p_j\) 表示在匹配到第 \(j\) 个字母而 \(j+1\) 个字母不能匹配是,可以移动到前面和当前相同的地方,也就是要 \(t_1t_2\dots t_{p_j}=t_{j-p_j+1}t_{j-p_j+2}\dots t_j\) 的最大值。

然后使得 \(s_{i-j+1}s_{i-j+2}\dots s_i=t_1t_2\dots t_j\) 继续进行匹配。

然后就很清晰了。

\(p\) 数组

自己匹配自己,然后就可以在匹配失败的时候移动到相同的地方以优化。

代码:
for(int i=1;i<m;++i){
    while(j>0&&t[j+1]!=t[i+1])
		j=p[j];
    if(t[i+1]==t[j+1])
		++j;
	p[i+1]=j;
}

Code

#include<bits/stdc++.h>
#define int long long 
using namespace std;
inline int read(){
	int x=0,f=1;
	char ch;
	ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-f;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=x*10+(ch-'0');
		ch=getchar();
	}
	return x*f;
}
char s[10000000],t[10000000];
int n,m,p[11000000];
signed main(){
    scanf("%s%s",s+1,t+1);
    p[1]=0;
    n=strlen(s+1),m=strlen(t+1);
    int j=0;
    for(int i=1;i<m;++i){
        while(j>0&&t[j+1]!=t[i+1])
			j=p[j];
        if(t[i+1]==t[j+1])
			++j;
		p[i+1]=j;
    }
    j=0;
    for(int i=0;i<n;++i){
        while
			j=p[j];
        if(t[j+1]==s[i+1])
			++j;
        if(j==m){
			cout<<i-m+2<<endl;
			j=p[j];
		}
    }
    for(int i=1;i<=m;++i)printf("%d ",p[i]);
    return 0;
}

时间复杂度为:\(O(n+m)\)(不会重复匹配)。

标签:dots,ch,匹配,int,笔记,KMP,字符串
From: https://www.cnblogs.com/pdpdzaa/p/17641166.html

相关文章

  • 【笔记】凸优化 Convex Optimization
    DifferentiationDef.Gradient\(f:{\calX}\sube\mathbb{R}^N\to\mathbb{R}\)isdifferentiable.Thenthegradientof\(f\)at\({\bfx}\in\cal{X}\),denotedby\(\nablaf({\bfx})\),isdefinedby\[\nablaf({\bfx})=\begin{bmatrix......
  • c语言笔记4
    c语言笔记4(指针)1.指针的应用1.1内存空间32位机:一次处理数据的大小4B(字节)64位机:一次处理数据的大小8B(字节)计算处理数据的最小单位是1B(字节),计算存储数据的最小单位二进制的1b(位)一个程序启动后的进程分区:栈、堆、全局区、常量区、代码区内存寻址:(32位)最大......
  • 洛谷P5410 【模板】扩展 KMP(Z 函数)题解
    题目链接P5410【模板】扩展KMP(Z函数)-洛谷|计算机科学教育新生态(luogu.com.cn) 分析先考虑z数组设nx[i]为字符串b与b以b[i]开头的后缀最长公共前缀设i为当前需要求的位置当前i+nx[i]-1的最大值所对应的i为q p为i对应的位置当i大于q+nx[q......
  • Linux 系统替换字符串常用命令
    概述在Linux系统中有时候我们需要替换某个很长的字符串或者修改某个配置参数,有些文件又隐藏目录比较深,有些场景也需要在一个目录下批量去修改文件,那应该怎么高效,快速的去完成修改呢?下面记录一下本人实施过程中的一些方法,做个备忘手稿分享以备随时查看。系统平台CentOSLinux7第......
  • 【刷题笔记】25. Reverse Nodes in k-Group
    题目Givenalinkedlist,reversethenodesofalinkedlistkatatimeandreturnitsmodifiedlist.kisapositiveintegerandislessthanorequaltothelengthofthelinkedlist.Ifthenumberofnodesisnotamultipleofkthenleft-outnodesint......
  • 【LeetCode2199. 找到每篇文章的主题】字符串处理题,使用MySQL里的group_concat和LOCAT
    题目地址https://leetcode.cn/problems/finding-the-topic-of-each-post/description/代码witht1as(selectp.*,k.*fromPostspleftjoinKeywordskonLOCATE(LOWER(CONCAT('',word,'')),LOWER(CONCAT('',conte......
  • openGauss学习笔记-44 openGauss 高级数据管理-存储过程
    openGauss学习笔记-44openGauss高级数据管理-存储过程存储过程是能够完成特定功能的SQL语句集。用户可以进行反复调用,从而减少SQL语句的重复编写数量,提高工作效率。44.1语法格式创建存储过程CREATEPROCEDUREprocedure_name[({[argname][argmode]argtype[......
  • Redis分布式锁笔记
    1redis分布式锁实现原理所谓分布式锁,应当基本如下几项核心性质:• 独占性:对于同一把锁,在同一时刻只能被一个取锁方占有,这是锁最基础的一项特征• 健壮性:即不能产生死锁(deadlock).假如某个占有锁的使用方因为宕机而无法主动执行解锁动作,锁也应该能够被正常传承下去,被其......
  • 云原生之使用Docker部署开源Leanote蚂蚁笔记
    (云原生之使用Docker部署开源Leanote蚂蚁笔记)一、Leanote蚂蚁笔记介绍1.Leanote简介Leanote蚂蚁笔记是一款云笔记工具,蚂蚁笔记(又名LeaNote)就是一款国产开源的私有云笔记软件。它支持普通格式笔记、Markdown语法、专业数学公式编辑、和思维脑图,常见的笔记相关功能它都拥有,同时......
  • springcloud学习笔记
    springcloud2020开始取消英国地铁命名方式。 注册中心、配置中心:nacos服务调用:feign服务熔断:sentinel网关:gateway链路:sleuth ......