算法之美--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算法 传统算法讲的是串与串依次一对一的比较,举例设 ...
随机推荐
- dedecms 搬家流程
进入后台 系统 点击数据备份/还原根据新空间数据库版本格式备份 进入网站根目录备份文件夹data\backupdataimagestempletsuploadsplus 进入新空间 重新安装dede程 ...
- 前端AI切图技巧
AI的基本使用 1.选中多个不同图层. 首先在AI右边工具栏找到“图层” 然后选择需要切图的图层(按住“ctrl”点击) 最后拖到PS里面的新建的图层. 还有个问题,就是图层关联太多,无法拖动某些图层 ...
- API生命周期第三阶段:API实施模式,以及结合swagger和项目现状的最佳模式
这篇博客,主要是宏观介绍一下开发模式,尤其是针对于目前公司前后分离的项目! 一.API实施模式概述 API实施模式,主要是三个,其中API-First又是作为一种指导思想的一种,所以,简单来说事实实施 ...
- ruby操作mysql
require "win32ole" require 'pathname' require 'mysql2' excel = WIN32OLE.new('excel.applica ...
- ACM程序设计选修课——1076汇编语言(重定向+模拟)
1076: 汇编语言 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 34 Solved: 4 [Submit][Status][Web Board] ...
- 背包问题--golang的入门解
. 定义一种 表示静态属性的 关键字 / 修饰符 2. 作用共用.共享 能有此作用的原因分析: Java中,任何变量 / 代码存储时,都是 在编译时 由系统自动分配内存在静态变量编译后,所分配的内存会 ...
- BZOJ2285 [SDOI2011]保密 【01分数规划 + 网络流】
题目 现在,保密成为一个很重要也很困难的问题.如果没有做好,后果是严重的.比如,有个人没有自己去修电脑,又没有拆硬盘,后来的事大家都知道了. 当然,对保密最需求的当然是军方,其次才是像那个人.为了应付 ...
- 算法复习——区间dp
感觉对区间dp也不好说些什么直接照搬讲义了2333 例题: 1.引水入城(洛谷1514) 这道题先开始看不出来到底和区间dp有什么卵关系···· 首先肯定是bfs暴力判一判可以覆盖到哪些城市····无 ...
- 标准C程序设计七---47
Linux应用 编程深入 语言编程 标准C程序设计七---经典C11程序设计 以下内容为阅读: <标准C程序设计>(第7版) 作者 ...
- py2exe使用方法 (含一些调试技巧,如压缩email 类)
http://justcoding.iteye.com/blog/900993 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样, ...