【Luogu P3375】字符串匹配KMP算法模板
- 模式串:即题目中的S2所代表的意义
- 文本串:即题目中的S1所代表的意义
对于字符串匹配,有一种很显然的朴素算法:在S1中枚举起点一位一位匹配,失配之后起点往后移动一位,从头开始进行匹配。
这种算法的时间复杂度几乎达到了\(O(nm)\),显然是不能接受的。
这种做法的缺点在于做了很多无用的匹配,并且每一次都从头开始匹配,完全忽略上一次匹配的信息。
而KMP算法就利用了上一次匹配的信息,减少匹配次数,时间复杂度仅有\(O(n)\)
(图片来自算法导论)
观察这样一张图。在第六位失配之后,按照朴素算法,我们把模式串后移一位,从头开始匹配。事实上后移一位的匹配根本不可能成功,根据上一次匹配得到的信息,因为文本串(灰色部分)中的第二位能够与模式串的第二位匹配,所以不可能与第一位匹配。而文本串(灰色部分)第三四五位恰好与模式串的第一二三位匹配,所以我们可以直接把模式串后移两位,重新开始匹配。
(图片来自算法导论)
如上图所示,这样可以减少很多不必要的匹配。
那么我们怎么才能知道让模式串偏移多少才合适呢?
下文的j是在模式串中的指针,j及其以前的字符是已经匹配的。
假设字符串在第j位失配,我们要找到一个尽可能长的长度\(L\),使\(S2[1..L]\)与\(S2[j-L,j]\)完全匹配(L<j),这样我们就可以在可以直接令\(j=L\),跳过前面L个的字符,因为他们绝对是匹配的。
结合代码及注释进行透彻的理解:(从KMP函数开始看更便于理解)
#include<cstdio>
#include<iostream>
using namespace std;
string s1,s2;
int nxt[1000005];
void Pre_do()
{
int len=s2.size();
nxt[0]=-1;//-1意味着从头开始匹配
for (int i=1,j=-1;i<len;i++)//注意i从1开始
{
while (j>=0&&s2[j+1]!=s2[i]) j=nxt[j];//假设不能匹配就跳过去。
//j一定小于i,所以此时的nxt[j]一定已经被记录了
if (s2[j+1]==s2[i]) j++;//匹配了就增加匹配长度
nxt[i]=j;//记录
}
}
int KMP()
{
int ret=0,len1=s1.size(),len2=s2.size();
for (int i=0,j=-1;i<len1;i++)
{
while (j>=0&&s2[j+1]!=s1[i]) j=nxt[j];//假设不能匹配就跳过去。
if (s2[j+1]==s1[i]) j++;//匹配了就增加匹配长度
if (j==len2-1) //匹配成功
{
ret++;
j=nxt[j];
printf("%d\n",i-len2+2);
}
}
return ret;
}
int main()
{
cin>>s1>>s2;
Pre_do();//预处理,求出每个位置失配后应该跳到哪个位置
KMP();
int len2=s2.size();
for (int i=0;i<len2;i++) printf("%d ",nxt[i]+1);
return 0;
}
【Luogu P3375】字符串匹配KMP算法模板的更多相关文章
- 字符串匹配KMP算法详解
1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...
- 字符串匹配KMP算法
1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- 字符串匹配KMP算法的C语言实现
字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...
- 字符串匹配KMP算法的讲解C++
转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...
- 字符串匹配KMP算法(转自阮一峰)
转自 http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字符串匹配是计算 ...
- 字符串匹配——KMP算法
关于KMP算法的分析,我觉得这两篇博客写的不错: http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html ht ...
- 字符串匹配—KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的核心是利用匹配失败后 ...
- P3375 【模板】KMP字符串匹配——kmp算法
先上一波题目 https://www.luogu.org/problem/P3375 kmp模板 看了好久才想起来是个什么东西qwq #include<cstdio> #include&l ...
随机推荐
- Spring MVC(2)Spring MVC 组件开发
一.控制器接收各类请求参数 代码测试环境: 接收各类参数的控制器--ParamsController package com.ssm.chapter15.controller; @Controller ...
- marquee滚动标签
marquee语法 <marquee></marquee> 实例一<marquee>Hello, World</marquee> marquee常 ...
- 关于./xhost: unable to open display问题的解决
看了很多大同小异的帖子,都没能解决这个问题,以下是我的实测经验,注意第三步,很关键. 注:以下操作在确保vncserver.xdpyinfo服务正常的情况下进行 第一步:root登录,启动vncser ...
- 题解【洛谷】CF134A
题解 CF134A [Average Numbers] 这题就是简单的模拟. 只不过要优化一下常数什么的 思路: 为了不浪费时间总是取平均数,直接用一个 S 储存总和,每次都减去 a_i 再除以 n ...
- NOIP模拟 4
T1没开longlong T2忘了有向... T3是个好题,可以说将复杂度从N^2优化到NlogN是一个质的飞跃 考虑分治(要想出log可不就要分治么!(segtree也行 但我不会) 对于一个分治区 ...
- P2114 [NOI2014]起床困难综合症
#include<iostream> #include<cstdio> using namespace std; ; ]; long long n,m; long long t ...
- Vue 2.x 3.x 配置项目开发环境跟线上环境
先找到package.json (这是nuxt版的vue 可能会跟一般vue不一样 当然总体上差不多的) "scripts": { "dev": " ...
- liunx查看日志 | 最实用命令和方法
1.业务系统访问量不是很大的时候,使用这个,有bug的地方操作下,直接看最后操作的日志 tail -fn100 catalina.log 查询日志尾部最后100行的日志,并且随文件; 2. ...
- 「每日五分钟,玩转 JVM」:GC 概览
前言 GC(Garbage Collection)是我们在学习 JVM 的过程中不可避免的一道坎,接下来,我们就来系统的学习一下 GC. 做一件事情之前,我们一定要去知道我们为什么要去做,这里不仅仅指 ...
- day1-习题
# 1.使用while循环输入 1 2 3 4 5 6 8 9 10 count = 1 while count<11 : #使用while语句循环输入123...10 if count == ...