kmp

algorithm@ KMP

北战南征 提交于 2020-02-07 09:21:39
一. KMP算法 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,简称KMP算法。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。 二. KMP算法的意义 先举一个简单模式匹配的例子,给定字符串T=“abababca”,S=“bacbababaabcbab”,判断T是否是S的子串,如果用暴力扫描的话,就是拿着T字符串从S的头扫到尾。这样的时间复杂度最坏情况下是O(n*m),其中n和m分别是主串和模式串的长度。而KMP算法的时间消耗是O(n+m)的,至于为什么这样,下面再说。 三. KMP算法的核心 KMP的核心就是一张表,我们称之为部分匹配表,起初我看这张表的时候也是云山雾绕,不知所云,部分匹配表是为模式串T专门设计的,T中每个字符对应着一个整数值,(这个地方也是困扰了我很久),现在我尽可能说得明白一些。首先下面附上一张T为“abababca”的部分匹配图,让大家“先睹为快”,看看部分匹配表是个什么东东。 好了,现在我们有了一个含有8个字符的模式串T,那么最后一行的value值是怎么得来的呢?别急,我先介绍相关概念:前缀和后缀,就拿字符串”abca“来说,”abca“的前缀有{a,ab,abc},

KMP&拓展KMP

邮差的信 提交于 2020-02-07 09:19:16
KMP算法 说明 KMP算法是一种比较高效的字符串匹配算法,可以在线性时间内求出一个串在另一个串的所有匹配位置。 解析 详解KMP 设模板串是 \(pattern\) 令 \(next[i] = max\{k|pattern[0...k-1]=pattern[i-k+1...i]\}\) , \(next[]\) 可以通过动态规划求解。 板子 \(next\) 数组存在的意义: 当 \(A\) 串匹配到 \(i\) , \(B\) 串匹配到 \(j\) 时, 如果发现失配,可以直接令 \(j = next[i]\) 然后继续匹配, ( \(next[i]\) 将记录如果 \(B\) 串匹配到 \(A\) 的 \(i\) 位置,前面有多少是已经匹配了的。) \(next\) 数组的求法 算法流程 : 初始化 \(next[1] = j = 0\) ,假设 \(next[1...i-1]\) 已经求出,下面求解 \(next[i]\) 不断尝试扩展长度 \(j\) , 如果扩展失败(下一个字符不相等),令 \(j\) 变为 \(next[j]\) , 直至 \(j = 0\) (应该从头开始匹配) 如果扩展成功,匹配长度 \(j\) 就增加 \(1\) , \(next[i]\) 的值就是 \(j\) 。 inline void calc_next() { next[1] = 0;

扩展KMP算法

你离开我真会死。 提交于 2020-02-07 09:18:53
一、何为扩展 预先设定 字符串S,长度为n 字符串T,长度为m 下标i从0开始 extend[i]表示: S[i]...S[n-1] 与 T 的 最长相同前缀 的长度 问题:求出所有的extend[i] 具体示例如下表所示: KMP 算法的功能 如果在 S 的某个位置 i 有 extend[i] 等于 m,则可知在 S 中找到了匹配串 T,并且匹配的首位置是 i; 扩展 KMP 算法可以找到 S 中所有 T 的匹配。 二、扩展KMP算法 【算法流程】 1. 如上图,假设当前遍历到 S 串位置 i,即 extend[0]...extend[i - 1] 这 i 个位置的值已经计算得到。设置两个变量,a 和 p。p 代表以 a 为起始位置的字符匹配成功的最右边界,也就是 “p = 最后一个匹配成功位置 + 1”。相较于字符串 T 得出, S[a...p) 等于 T[0...p-a) 。 再定义一个辅助数组 int next[] ,其中 next[i] 含义为: T[i]...T[m - 1] 与 T 的最长相同前缀长度,m 为串 T 的长度。 举个例子: 2. 椭圆的长度为 next[i - a] ,对比 S 和 T,很容易发现,三个椭圆完全相同。如上图,此时 i + next[i - a] < p ,根据 next 数组的定义,此时 extend[i] = next[i - a] 。

KMP算法

你。 提交于 2020-02-07 09:18:37
这篇文章想简单讲讲 KMP 算法的内容。 KMP 算法 KMP 算法由 Knuth–Morris–Pratt 三个人共同提出,它的目的是判断字符串 A 中是否包含另一个字符串 B(如:判断 abababaababacb 中是否包含 ababacb )。 KMP 算法流程 KMP 下面演示一下 KMP 的流程。假设我们要判断字符串 A(abababaababacb)中是否包含字符串 B(ababacb)。 我们分别用两个指针 i 和 j 指示 A、B 匹配的位置。 首先比较第一个位置: i: 0 A: a B: a j: 0 匹配了 a 跟 a,向前移动指针 i 和 j : i: 01 A: ab B: ab j: 01 匹配了 b,继续向前移动指针 i 、 j ,直到: i: 01234 5 A: ababa b B: ababa c j: 01234 5 按照常规的方法,我们要把 i 从上次起始点 0 移动到 1,而 j 则回到 0 继续匹配。但你是否注意到一个现象:我们已经用 B 的 ababa 匹配了 A 的 ababa,也就是说,我们已经掌握 A、B 前面这部分的信息,那么,对于前面这部分信息能否相互匹配,我们其实已经知道了。 比如说,我们没有必要把 i 和 j 重新调回 1 和 0,因为 A[1] 和 B[0] 肯定是不匹配的。最明智的做法是调成下面这种状态: i:

KMP算法

泄露秘密 提交于 2020-02-07 09:18:24
字符串匹配中经常会用到KMP算法。它求解的问题类型是:字符串匹配。给你两个字符串,寻找其中一个字符串是否包含另一个字符串,如果包含,返回包含的起始位置。 我们一般的做法是:将一个字符串(长度为n,模式串)放在另一个字符串(长度为m,主串)开始的位置,然后依次比较,如果有不匹配的字符,就将字符串往后移一位,然后依旧从头开始比较。直到找到完全匹配的位置,返回。遍历顺序从0到m-n,每次遍历,都要比较n(最多)次,所以复杂度近似为O(m*n); 而我们今天说的这个KMP算法,可以达到O(m+n)的复杂度。 算法基本思想:每次当匹配失败时,没有必要就移动一位,因为前面可能有已经匹配的字符了。如果模式串当前的字符存在公共前后缀,那么我可以对于每一个模式串事先计算出模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。 注意最长前缀: 是说以第一个字符开始,但是不包含最后一个字符 KMP有个next数组,用来存放模式串中内部的匹配信息。举个例子,比如模式串为 ababaca ,长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是 a , ab , aba , abab , ababa , ababac , ababaca 的相同的最长前缀和最长后缀的长度。由于 a , ab , aba ,

php 实现KMP算法

 ̄綄美尐妖づ 提交于 2020-02-07 09:07:06
简介:这是php 实现KMP算法的详细页面,介绍了和php,php, kmp, 数据结构, 算法 php 实现KMP算法有关的知识、技巧、经验,和一些php源码等。 class='pingjiaF' frameborder='0' src='http://biancheng.dnbcw.info/pingjia.php?id=360997' scrolling='no'> <? php /** * KMP算法的PHP实现 * * @author zhaojiangwei 2011/10/22 10:28 */ class KMP{ private $next = NULL; //模式串T的next数组 private $t = NULL; //模式串 private $str = NULL; //主串 public function KMP($str){ $this->str = str_split($str); $this->next = array(); } //返回主串的长度 public function getStrCount(){ return count($this->str); } //返回结果 public function getStrPos($substr){ $substr = str_split($substr); $this->getNext(

Substring Frequency(KMP)

廉价感情. 提交于 2020-02-06 19:22:30
A string is a finite sequence of symbols that are chosen from an alphabet. In this problem you are given two non-empty strings A and B, both contain lower case English alphabets. You have to find the number of times B occurs as a substring of A. Input Input starts with an integer T (≤ 5), denoting the number of test cases. Each case starts with two lines. First line contains A and second line contains B. You can assume than 1 ≤ length(A), length(B) ≤ 106. Output For each case, print the case number and the number of times B occurs as a substring of A. Sample Input 4 axbyczd abc abcabcabcabc

KMP字符串

不问归期 提交于 2020-02-05 00:36:17
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。 模板串P在模式串S中多次作为子串出现。 求出模板串P在模式串S中所有出现的位置的起始下标。 输入格式 第一行输入整数N,表示字符串P的长度。 第二行输入字符串P。 第三行输入整数M,表示字符串S的长度。 第四行输入字符串S。 输出格式 共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。 数据范围 1 ≤ N ≤ 10 4 1≤N≤104 1 ≤ M ≤ 10 5 1≤M≤105 输入样例: 3 aba 5 ababa 输出样例: 0 2 思路:1.求next数组,做此题字母下标从1开始。定义两个指针i = 2,j = 0,因为next[1] = 0 不用计算,所以计算next数组时i的初始值是2。每次比较的是p[j + 1] 和 s[i]。如果二者相等,j = ne[j]。     next数组的含义如下所示:代码: 1 for(int i = 2 , j = 0 ; i <= n ; i ++){ //ne[1] = 0 ,不用算,所以i从2开始 2 3 while(j && p[j + 1] != p[i]) j = ne[j]; //如果不相等,j往前跳 4 5 if(p[j + 1] == p[i]) j ++; //相等的话,j后移 6 7 ne[i] = j;

LeetCode 28. Implement strStr() - KMP

守給你的承諾、 提交于 2020-02-04 20:45:08
题目链接: 28. Implement strStr() Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Example 1: Input : haystack = "hello" , needle = "ll" Output : 2 Example 2: Input : haystack = "aaaaa" , needle = "bba" Output : - 1 Clarification: What should we return when needle is an empty string? This is a great question to ask during an interview. For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strstr() and Java’s indexOf() . 题解 双指针算法就是从匹配串的第一个字符开始一个一个的匹配,直到结束或找到为止。

算法学习——KMP字符串匹配算法

百般思念 提交于 2020-02-04 15:41:32
KMP算法是一种非常高效和常用的算法。其核心就是通过预处理一个寻找公共最大前后缀的 Next[ ] 数组,减少匹配失败时的重复无效匹配。 next数组本质:next[ i ] = j 表示下标以 i - j 为起点,i为终点的后缀和下标以0为起点,j为终点的前缀相等。 复制一些别人的图片用来帮助理解next是什么。 然后是kmp算法的思想原理: 下图是主串为:ababaeaba 字串为:ababacd 的一个例子; 例题: 代码: #include<iostream> using namespace std; const int N = 1000010; //a[]是主串,b[]是模式串,在a[]中寻找b[] char a[N],b[N]; //ne[]是next数组,由于c++中存在next关键字,所以我们为了避免编译错误,起名ne[] int ne[N]; //n是主串长度,n是子串(模式串)长度 int n,m; //预处理ne数组 void prekmp(){ //模板串长度为1时无前后缀,所以循环从2开始 for(int i = 2,j = 0;i <= m ;i++){ //如果刚开始开始匹配或者匹配失败,就返回上一层匹配 while( j && b[i] != b[j+1]) j = ne[j]; //如果匹配成功 if(b[i] == b[j+1]) j++; /