引言

众所周知,字符串无论是在 OI 中还是别的计算机领域都占有比较大的比重,今天说的就是一个关于匹配字符串的算法——「 KMP 算法 」。

0x00

KMP 算法用于解决这样的一类问题:给定一个文本串 T 和模式串 S,要求你求出 S 在 T 中出现的次数和位置(我们定义位置为 S 中第一个字符在 T 中匹配到的位置)

当然它还有许多别的用法。具体的可以通过一道题目来体现一下 HDU 3336

0x01

我们都知道朴素的匹配字符串的算法,不知道的看下面这个例子。

文本串:ABADCADCAB
模式串:ADCAB
  1. A 和 A 匹配,比较下一位。一直到发现 B 和 D 不匹配。
  2. 不匹配就将模式串后移一位。
  3. A 和 B 不匹配,重复之前的过程直到匹配完成。

但是我们发现下面这种情况

ABABCADCAB
  ADCAB

最后一位 B 和 D 并不能匹配。但是按照朴素算法的话会将模式串一位一位的往后移动。

直到出现下面的情况

ABABCADCAB
     ADCAB

试想,如果在第五位失配后我们可以直接将模式串的第一位直接移动到第四位。

虽然我们能够看出这样很简单,但如何让计算机也看出来呢?

这里我们引入一个 $next$ 数组,通俗的说,$next[i]$ 含义就是长度为 $i$ 的模式串前缀的前缀和后缀所共有的最长的字串。

我们先不说 $next$ 数组怎样求,先来说说它怎么用。

是不是很绕口呢

我们看看这句话是啥意思

模式串:ADCAB
前缀:A,AD,ADC,ADCA
后缀:B,AB,CAB,DCAB

上面这个就是在一个长度为 $5$ 的前缀中所有的前缀和后缀

我们看这些前后缀中有哪些是满足有共同的元素的

只有下面这两个

AD,AB

它们返回的 $next$ 值是 $1$,也就是说在第五位失配之后,第一位就会跳到第四位去继续匹配。

0x02

这个 next 数组怎么求出来的。

我们试图让模式串自己匹配自己。

说到这里大概就知道为什么之前不告诉大家怎么求 $next$ 数组了吧?

因为这个 $next$ 数组会用了就会求了。而两者相比的话,「 用 」这一方面比较简单好理解

看下面这个求 $next$ 数组的代码。

inline void Getnext() {
for(int i=; i<=n; i++) {
p = nxt[i-];
//i的前一位在失配后哪一位会跳过来
while(p && s[p+] != s[i]) p = nxt[p];
//如果next[i]这一位还是不能和s[i]匹配,那就继续往前跳
//这句话中p!=0表示如果跳到第一位就可以不用跳了
if(s[p+] == s[i]) nxt[i] = p+;
//如果找到了能够匹配的,就更新next[i]
else nxt[i] = ;
//找不到就是0
}
}

下面贴一下完整的代码

#include <iostream>
#include <cstdio>
#include <cstring>
const int maxn = 1e6+;
using namespace std;
int n, m, next[maxn], p;
char T[maxn], S[maxn];
inline void Getnext() {
for(int i=; i<=n; i++) {
p = next[i-];
while(p && s[p+] != s[i]) p = next[p];
if(s[p+] == s[i]) next[i] = p+;
else next[i] = ;
}
}
int main() {
scanf("%s%s", T+, S+);
n = strlen(T+), m = strlen(S+);
Getnx();
p = ;
for(int i=; i<=n; i++) {
while (p && T[i] != S[p+]) p = next[p];
if(T[i] == S[p+]) p++;
else p = ;
if(p == m) printf("%d\n", i-m+), p = next[p];
}
for(int i=; i<=m; i++) {
printf("%d ", next[i]);
}
}

字符串匹配「 KMP 算法 」的更多相关文章

  1. Luogu 3375 【模板】KMP字符串匹配(KMP算法)

    Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...

  2. 字符串匹配的 KMP算法

    一般字符串匹配过程 KMP算法是字符串匹配算法的一种改进版,一般的字符串匹配算法是:从主串(目标字符串)和模式串(待匹配字符串)的第一个字符开始比较,如果相等则继续匹配下一个字符, 如果不相等则从主串 ...

  3. 字符串匹配的kmp算法 及 python实现

    一:背景 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的常 ...

  4. HDU 1711 Number Sequence (字符串匹配,KMP算法)

    HDU 1711 Number Sequence (字符串匹配,KMP算法) Description Given two sequences of numbers : a1, a2, ...... , ...

  5. 字符串匹配(KMP 算法 含代码)

    主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知 ...

  6. 实现字符串匹配的KMP算法

    KMP算法是Knuth-Morris-Pratt算法的简称,它主要用于解决在一个长字符串S中匹配一个较短字符串s. 首先我们从整体来把我这个算法的思想. 字符串匹配的朴素算法: 我们容易想到朴素算法, ...

  7. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  8. 字符串匹配的KMP算法详解及C#实现

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  9. 字符串匹配与KMP算法实现

    >>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个 ...

随机推荐

  1. 学习MAP 地图好地址

    http://www.cnblogs.com/beniao/archive/2010/01/13/1646446.html Bēniaǒ成长笔记在IT江湖里我不是一名老手,我只是一名普通的程序员,愿意 ...

  2. bzoj1854 [Scoi2010]游戏——匈牙利算法

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1854 这题...据说可以用并查集做,但没有去看... 用二分图匹配的话,就把装备和它的两个属 ...

  3. MSD6A628开发资料与技术支持

    MSD6A628VX/VXM是mstar推出的低成本安卓智能网络电视方案,628分两个版本,一个是内置512MB内存,一个是外挂1G内存, 安卓4.4系统,4核A7处理器,Mali450MP2 GPU ...

  4. U74201 旅行计划 树上找链长度

    题目背景 珂朵莉放假了,她打算去唐山旅行. 题目描述 我们简单地把唐山的共 nn 个景点看成是一棵树,有 n-1n−1 条边将它们连接起来,每个景点有一个游览指数 v_ivi​.珂朵莉的假期时间不长, ...

  5. Ruby on Rails5 直接的路径无效问题

    比如设置个背景 background = "../../assets/images/test1.jpg" 会发现无效   网上一翻,Rails里面直接指定无效.   解决方法就是把 ...

  6. jQuery 表格隔行变色插件

    jQuery提供了用于扩展jQuery功能的方法,即jQuery.fn.extend()方法和jQuery.extend()方法. 基本的JS框架代码如下: ;(function($) { $.fn. ...

  7. P2746 [USACO5.3]校园网Network of Schools(Tarjan)

    P2746 [USACO5.3]校园网Network of Schools 题目描述 一些学校连入一个电脑网络.那些学校已订立了协议:每个学校都会给其它的一些学校分发软件(称作“接受学校”).注意即使 ...

  8. Akka源码分析-Cluster-Distributed Publish Subscribe in Cluster

    在ClusterClient源码分析中,我们知道,他是依托于“Distributed Publish Subscribe in Cluster”来实现消息的转发的,那本文就来分析一下Pub/Sub是如 ...

  9. Linux下安装网络软件的步骤

    Linux下安装网络软件的步骤(给linux初学者,linux大神请绕路) 首先下载你所需要的软件带有deb后缀的文件 然后切换到该文件的目录 切换到超级用户权限或者是(sudo) 使用sudo dp ...

  10. 数学/思维 UVA 11300 Spreading the Wealth

    题目传送门 /* 假设x1为1号给n号的金币数(逆时针),下面类似 a[1] - x1 + x2 = m(平均数) 得x2 = x1 + m - a[1] = x1 - c1; //规定c1 = a[ ...