算法之美--3.2.3 KMP算法
不知道看了几遍的kmp,反正到现在都没有弄清楚next[j]的计算和kmp的代码实现,温故而知新,经常回来看看,相信慢慢的就回了
理解KMP
/*!
* \file KMP_算法.cpp
*
* \author ranjiewen
* \date 2017/02/12 16:12
*
*/ void preKmp(const char* pattern, int m, int kmpNext[]) //和GetNextval等价
{
int i, j;
i = ;
j = kmpNext[] = -;
while (i<m)
{
while (j>- && pattern[i] != pattern[j]) // i为后缀,j为前缀
{
j = kmpNext[j];
}
i++;
j++;
if (pattern[i] == pattern[j])
{
kmpNext[i] = kmpNext[j];
}
else
{
kmpNext[i] = j;
}
}
} #include <iostream>
using namespace std;
#include <string> void KMP(string p, string t)
{
int m = p.length();
int n = t.length();
if (m>n)
{
cerr << "Unsuccessful match!";
}
const char* x = p.c_str();
const char* y = t.c_str(); int i = , j = , kmpNext[];
preKmp(x, m, kmpNext); i = j = ;
while (i<n)
{
while (j>- && x[j] != y[i])
{
j = kmpNext[j];
}
j++;
i++;
if (j >= m)
{
cout << "Matching index found at:" << i - j << endl;
j = kmpNext[j];
}
}
}
int main(int argc, char** argv) { string p1 = "abcabcad";
string p2 = "adcadcad";
string p3 = "ababcaabc";
string t = "ctcabcabcadtcaabcabcadat"; cout << "KMP: " << endl;
KMP(p1, t); // cout<<"KMP: "<<endl;
// KMP(p2, t); // cout<<"KMP: ";
// KMP(p3, t); return ;
}
- 以后kmp算法都按照这样写
void GetNext(char* p, int next[])
{
int pLen = strlen(p);
next[] = -;
int k = -;
int j = ;
while (j < pLen - ) //j<pLen也没有错
{
//p[k]表示前缀,p[j]表示后缀
if (k == - || p[j] == p[k])
{
++k;
++j;
next[j] = k; //对于值k,已有p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,相当于next[j] = k。
}
else //当不匹配时,更新新的前缀下标
{
k = next[k];
}
}
} // 优化的地方
//当p[j] != s[i] 时,下次匹配必然是p[next[j]] 跟s[i]匹配,如果p[j] = p[next[j]],必然导致后一步匹配失败(因为p[j]已经跟s[i]失配,
//然后你还用跟p[j]等同的值p[next[j]]去跟s[i]匹配,很显然,必然失配),所以不能允许p[j] = p[next[j]]。
//优化过后的next 数组求法
void GetNextval(char* p, int next[])
{
int pLen = strlen(p);
next[] = -;
int k = -; //前缀
int j = ;
while (j < pLen - ) //j<pLen也没有错
{
//p[k]表示前缀,p[j]表示后缀
if (k == - || p[j] == p[k])
{
++j;
++k;
//较之前next数组求法,改动在下面4行
if (p[j] != p[k])
next[j] = k; //之前只有这一行
else
//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]
next[j] = next[k];
}
else
{
k = next[k];
}
}
} int KmpSearch(char* s, char* p)
{
int i = ;
int j = ;
int sLen = strlen(s);
int pLen = strlen(p); int next[] = { };
GetNextval(p,next); while (i < sLen && j < pLen)
{
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == - || s[i] == p[j])
{
i++;
j++;
}
else
{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = next[j];
}
}
if (j == pLen)
return i - j; //此处i-j才是字符串开始匹配的地方
else
return -;
}
有这样写的,else效果就是j==-1的时候
while (Text[i] != '\0' && Pattern[j] != '\0')
{
if (Text[i] == Pattern[j])
{
++i;// 继续比较后继字符
++j;
}
else
{
index += j - next[j];
if (next[j] != -)
j = next[j];// 模式串向右移动
else
{
j = ;
++i;
}
}
}//while
算法之美--3.2.3 KMP算法的更多相关文章
- 字符串查找算法总结(暴力匹配、KMP 算法、Boyer-Moore 算法和 Sunday 算法)
字符串匹配是字符串的一种基本操作:给定一个长度为 M 的文本和一个长度为 N 的模式串,在文本中找到一个和该模式相符的子字符串,并返回该字字符串在文本中的位置. KMP 算法,全称是 Knuth-Mo ...
- JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)
1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...
- 算法之美--3.2.2 MP算法
这块硬骨头,放在这里半年的时间了,一直没有动,今天周末看看,书上把过程写的比较详细,自己基本也看懂了,但是对代码本身的编写还是比较生疏,要经常复习,估计才能看透,后面有看了kmp;这两者之间的关系也是 ...
- 利用KMP算法解决串的模式匹配问题(c++) -- 数据结构
题目: 7-1 串的模式匹配 (30 分) 给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串 ...
- KMP算法(转载)
转载http://blog.csdn.net/yutianzuijin/article/details/11954939 kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以 ...
- kmp算法简明教程
在字符串s中寻找模式串p的位置,这是一个字符串匹配问题. 举例说明: i = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 s = a b a a c a b a a a b a a ...
- 字符串模式匹配KMP算法
一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...
- kmp算法理解与记录
字符串匹配的暴力解法 给定字符串s和p,寻找字符串p在字符串s中出现的位置,暴力解法如下所示: 如果当前字符匹配成功,++i;++j,继续匹配下一字符. 如果s[i]与s[j]匹配失败,令i-=(j- ...
- 串匹配模式中的BF算法和KMP算法
考研的专业课以及找工作的笔试题,对于串匹配模式都会有一定的考察,写这篇博客的目的在于进行知识的回顾与复习,方便遇见类似的题目不会纠结太多. 传统的BF算法 传统算法讲的是串与串依次一对一的比较,举例设 ...
随机推荐
- Makefile基础(一)
在大型的C语言项目中,一般都是由多个源文件编译链接形成的可执行程序,而这些源文件的处理步骤,通常交给Makefile来管理,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后 ...
- RHEL6.X设置163yum源
目录 RHEL6.X设置163yum源 卸载系统的yum 检查是否已经卸载完成 下载yum以及相关包 安装yum相关rpm包 清除原有缓存,建立yum列表 本地yum源设置 挂载本地光盘 修改配置文件 ...
- linux 复制部分文件到另外的文件夹
show the command: |xargs -i cp {} ../ 或者指定目录 |xargs -i cp {} /home/peter
- 30行js让你的rem弹性布局适配所有分辨率(含竖屏适配)
用rem来实现移动端的弹性布局是个好主意!用法如下: CSS @media only screen and (max-width: 320px), only screen and (max-devic ...
- Ubuntu 14.04 LTS 安装和配置Bochs
Ubuntu 14.04 LTS 安装和配置Bochs 系统是:Ubuntu 14.04 LTS 64位 安装的是:bochs-2.6.8 Bochs 需要在 X11 环境下运行,因此你的 ...
- [Uiautomator篇][2] UiDeviceAPI介绍
1 https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html http://www.cnb ...
- Welcome-to-Swift-04集合类型(Collection Types)
Swift提供了两种集合类型来存放多个值——数组(Array)和字典(Dictionary).数组把相同类型的值存放在一个有序链表里.字典把相同类型的值存放在一个无序集合里,这些值可以通过唯一标识符( ...
- 【Luogu】P3806点分治模板(点分治)
题目链接 wc听不懂lca讲的高等数学专场(一个字都听不懂),然后就自学了点分治. 点分治就是我先处理完跟根有关的东西,然后把根标记掉,把原树拆成若干个联通块,然后分别对每个联通块(每个小树)搞一模一 ...
- jsp实现文件下载,out = pageContext.pushBody();out.close();不用写到jsp中
测试jsp: <%@ page contentType="text/html; charset=gbk" %> <% try{ com.enfo.intrust. ...
- UGUI 点击穿透问题
unity上 用 做游戏欢迎界面上通用的ui,然后导到游戏里面直接用,但发现游戏里面是用ngui的,点击ugui 的ui 会穿透过去 ngui会响应,原本模型的点击处理也会响应 我用的 unity 版 ...