kmp算法

[一本通学习笔记] KMP算法

為{幸葍}努か 提交于 2019-11-30 17:38:50
KMP算法 对于串s[1..n],我们定义fail[i]表示以串s[1..i]的 最长公共真前后缀 。 我们首先考虑对于模式串p,如何计算出它的fail数组。定义fail[0]=-1。 根据“真前后缀”的条件,容易得到fail[1]=0 对于任意的i>1,显然在s[fail[i-1]+1]==s[i]的时候,我们有fail[i]=fail[i-1] 如果s[fail[i-1]+1]!=s[i],那么我们需要去尝试s[fail[fail[i-1]]+1]是否与s[i]相等,否则再继续下去。 这是因为我们最终要找的是s[1..i]的最长公共前后缀,如果它不是由s[1..i-1]的最长公共前后缀扩增而来,那么它一定是由s[1..fail[i-1]]的最长公共前后缀扩增而来。毕竟,最长公共前后缀包含了若干个公共前后缀。即s[1..fail[i-1]]的最长公共前后缀也是s[1..i-1]的一个公共前后缀,虽然它未必最长。 // Build fail array for pattern string for(int i=2;i<=m;i++) { fail[i]=fail[i-1]; while(p[fail[i]+1]-p[i] && fail[i]) fail[i]=fail[fail[i]]; if(p[fail[i]+1]==p[i]) ++fail[i]; }  fail[0]=

模板——KMP算法

ぃ、小莉子 提交于 2019-11-30 15:19:21
关于子串的查找 1 char a[maxn],b[maxn]; 2 int lena,lenb,net[maxn]; 3 void getnet() { ///得到next数组 4 lenb=strlen(b); 5 net[0]=-1; 6 int i=0,j=-1; 7 while(i<lenb) { 8 if(j==-1||b[i]==b[j]) 9 net[++i]=++j; 10 else j=net[j]; 11 } 12 return ; 13 } 14 int getans() { ///KMP查找b串在a中的出现次数 15 lena=strlen(a); 16 lenb=strlen(b); 17 int ans=0; 18 if(lena==lenb&&lena==1) { 19 if(a[0]==b[0]) return 1; 20 else return 0; 21 } 22 for(int i=0,j=0;i<lena;i++) { 23 while(j>0&&a[i]!=b[j]) j=net[j]; 24 if(a[i]==b[j]) ++j; 25 if(j==lenb) ans++,j=net[j]; 26 } 27 return ans; 28 } View Code 来源: https://www.cnblogs.com/wuliking/p

kmp算法的思考与白话解释,一看就懂

旧街凉风 提交于 2019-11-30 06:08:55
这是一个判断字符串A是否包含在B中的问题, 比如(A) "abgab" 与(B) "abcabf abgab " kmp的思路是先分析要匹配的字符串A的内在结构特点 ,做出一张表格记录他的内部特征,然后匹配的时候就可以根据这个字符串的特征查询已经匹配的信息,对B跳跃式的比较,具体比较方法后面在说,先看看他怎么分析特征的. abgab的特征计算方法: 1,为每一个子串计算前缀与后缀相匹配的最大字符长度 前缀就是从第一个字符开始的一系列子串,但不包含A字符串的最后一个字符 后缀类似,但是不包含A字符串的第一个字符 那么可以得到一张静态的字符串的特征表 那么到这里A字符串的特征就分析完了 怎末用呢? 一个公式如下: 下一次要跳跃到的地址=上一次匹配的开始地址+(已经匹配的长度-A字符串在B字符串中最后一个匹配的字串的特征值) 比如:上面我举得栗子: abcabf abgab (B) abgab (A) 这里写出步骤: 1:位置0,从第一字符开始: c与g比较失败,因为已经匹配的ab特征值为0,长度为2,要跳到的地址=0+(2-0) , 此时A从0开始到B字符串上的c开始比较 2:位置为2,c与g不匹配,那么向后继续走到下一个字符 --a, 3: 位置3,f与g比较失败,因为已经匹配的ab特征值为0,长度为2,下一个地址=3+(2-0),A字符串下一个比较的地址为5 4:位置5

kmp算法

醉酒当歌 提交于 2019-11-30 03:17:52
具体参考 https://www.cnblogs.com/ciyeer/p/9035072.html /** * 创建next数组(数组第0位没作用, 从第1位才是有效位) * @param pattern * @return */ static int[] makeNext(String pattern) { char[] chars = pattern.toCharArray(); int[] next = new int[chars.length + 1]; int i = 1; next[1] = 0; int j = 0; while (i < chars.length) { if (j == 0 || chars[i-1] == chars[j-1]) { i++; j++; next[i] = j; } else { j = next[j]; } } return next; } /** * kmp方法查询字符串(快速模式匹配算法) * 源字符串中的索引i不会回溯, 比对字符串时 * 找到不一样的, 移动模式串的索引j来与源串中i位置再继续比较 * @param src * @param pattern * @return */ public static int kmpFindStr(String src, String pattern) { int[] next

KMP算法JS实现

孤者浪人 提交于 2019-11-29 22:30:10
参考阮一峰的《字符串匹配的KMP算法》,用JS实现一版,备忘~ // 主串 let str1 = 'BBC ABCDAB ABCDABCDABDEDC'; // 模式串 let str2 = 'ABCDABD'; /** * 算出《部分匹配表》Partial Match Table * 参考文档:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html * @method * @param {String} str 要计算的字符串 * @return {Array} 部分匹配表 */ let getPMT = (str = '') => { if(str.length === 0)return []; let pmt = [0]; let k = 2; while(k <= str.length){ let temp = str.substring(0, k); let length = temp.length; // 前缀 let prefix = temp.substring(0, length - 1).split('').map((item, index) => { return temp.substring(0, index + 1); }); //

KMP算法

拥有回忆 提交于 2019-11-29 22:25:06
KMP算法 暴力匹配算法 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有: 如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符; 如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0。 理清楚了暴力匹配算法的流程及内在的逻辑,咱们可以写出暴力匹配的代码,如下: int ViolentMatch(char* s, char* p) { int sLen = strlen(s); int pLen = strlen(p); int i = 0; int j = 0; while (i < sLen && j < pLen) { if (s[i] == p[j]) { //①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++ i++; j++; } else { //②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0 i = i - j + 1; j = 0; } } //匹配成功,返回模式串p在文本串s中的位置,否则返回-1 if (j == pLen) return i -

KMP算法

筅森魡賤 提交于 2019-11-29 10:16:28
朴素的字符串匹配算法 这是最容易理解的字符串匹配算法,我们用两个指针ai,bi分别指 待匹配串a 和 模式串b 的起始位置,当a[ai]==b[bi]时ai++,bi++,一旦失配,ai=ai-bi+1(原来位置的后一位),bi=0; 显然这种方法不断重复访问模式串的前部分使得匹配速度变慢 例如 a串:aaaaaaaaaaaaaaaaab b串:aaaaaaaaaab 每次匹配时我都要将b串访问一遍,原因在于每次匹配失败我都将bi回到0; 对于这里的改进就要引入next数组来记录一个合适的位置使得bi不用每次都回到0 next数组 int next[b.size()]; for(int i=1;i<b.size();i++) next[i]=0; next[0]=-1; next[1]=0; for(int i=2;i<b.size();i++) { int k=next[i-1]; if(b[k]==b[i-1]) next[i]=k+1; else { while(k!=-1) { k=next[k]; if(b[k]==b[i-1]) break; } next[i]=k+1; } } 这里是kmp算法最重要的部分 next数组的作用是当第i位的字符失配的时候bi回到next[bi]的位置 next[i]的实际意义是 i位置以前的next[i]个字符(不包括 i )

KMP

﹥>﹥吖頭↗ 提交于 2019-11-29 09:52:52
hdu 1711 hdu 1711 kmp模板题: #include<stdio.h> #include<string.h> #define N 1000005 int s[N]; int p[N]; int next[N]; int m,n; void getnext(){ int j=0,k=-1; next[0]=-1; while(j<m){ if(k==-1||p[j]==p[k]){ j++; k++; next[j]=k; } else k=next[k]; } } int kmp(){ int i=0,j=0; getnext(); while(i<n){ if(j==-1||s[i]==p[j]){ i++; j++; } else j=next[j]; if(j==m) return i; } return -1; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&s[i]); for(int i=0;i<m;i++) scanf("%d",&p[i]); if(kmp()==-1) printf("-1\n"); else printf("%d\n",kmp()-m+1); } return 0; }

KMP

女生的网名这么多〃 提交于 2019-11-28 17:43:05
前言 PMT:PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度 Next数组:PMT向后移一位,最前位补-1。每个位置记录的则是前面的字符串的前缀集合与后缀集合的交集中最长元素的长度 代码 package newcoder; /** * KMP算法 * */ public class Kmp { /** * <P>构造next数组</P> * <p> patternStr自己匹配自己得到next数组(自己的前缀匹配自己的后缀) * @param patternStr 模式串 * @return 模式串的next数组 */ public static int[] getNext(String patternStr) { char[] strs = patternStr.toCharArray(); int[] next = new int[strs.length]; next[0] = -1; // 首位为-1,前面不存在匹配情况 int j = 0; // 用于遍历strs数组 int k = -1; // 匹配数量 while(j < strs.length-1) { // 下一位记录前面的,所以只遍历到到数第二位 if(k == -1 || strs[j] == strs[k]) { if(strs[++j] == strs[++k]) { // 优化部分:失配时

字符串模式匹配KMP算法

允我心安 提交于 2019-11-28 10:03:03
字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。 朴素的模式匹配算法 很直观的可以写出下面的代码,来找出模式串在一个长字符串中出现的位置。 1: /* 2: 朴素的模式匹配算法 3: 功能:字符串的模式匹配 4: 参数: 5: s:目标串 6: p:模式串 7: pos:开发匹配的位置 8: 返回值: 9: 匹配成功,返回模式串在目标串的其实位置 10: 匹配不成功,返回-1 11: */ 12: int match(const char * s ,const char * p,int pos){ 13: int i = pos ; 14: int j= 0 ; 15: while(s[i] != '\0' && p[j] != '\0') { 16: if(s[i] == p[j]) { 17: i ++ ; 18: j ++ ; 19: }else { 20: i = i - j + 1; 21: j = 0 ; 22: } 23: } 24: 25: if(p[j] == '\0') 26: return i - j ; 27: else 28: return -1 ; 29: } /*--> */ /*--> */ 上面的代码,s就是目标串,p是模式串,pos指定从s的什么位置开始匹配p。其实现思想也很简单: 当s[i] == p[j]时