例题

以字符串 ABABACA 为例

a

前缀:

后缀:

结果为0

ab

前缀:a

后缀: b

结果为0

aba

前缀:a ab

后缀: ba a

结果为1,此时 i=2,j=1

abab

前缀:a ab aba

后缀: bab ab b

结果为2,此时 i=3,j=2

ababa

前缀:a ab aba abab

后缀: baba aba ba a

结果为3,此时 i=4,j=3

ababac

前缀:a ab aba abab ababac

后缀: babac abac bac ac c

结果为0,此时 i=5,j=3,1,0

ababaca

前缀:a ab aba abab ababac ababaca

后缀: babaca abaca baca bac ac c

结果为1,此时 i=6,j=0

next数组结果:

0 0 0 1 2 3 0 1

总结

以i为尾,往前数对应值,即是相等的,前提是相等的情况下(废话!);

前缀:要第一个字母,不要最后一个字母;

后缀:不要第一个字母,要最后一个字母;

至于i+1,因为计算的是前缀和后缀的重合的值的长度,所以还需要加上1;

最重要的是

j = next[i - 1],比如说现在在 i 位置上不匹配,为了避免重复匹配,不想浪费之前 0 到 i-1 的匹配长度,也就是说要找以 0 开头,i-1 结尾的匹配的子串,就是说找字符串上 i-1 位置的重合长度,因为next数组存储的是前缀和后缀的重合长度,所以还需要 i-1-1,也就是找next[i-1-1]的值,此时我们再比较字符串上 i 和 j 位置的字符是否相等;

如果相等 j 就尽管移动,代表重合的长度,也就是说到了该位置不匹配,只需要向前移动next数组中对应的长度。



贴上代码:

#include <iostream>
#include <string>
#include <vector>
using namespace std; vector<int> getNext(string str) {
int len = str.size();
int j = 0; vector<int>next(len + 1);
next[0] = next[1] = 0; // j表明相同的个数
for (int i = 1; i < len; i++) {
while (j > 0 && str[i] != str[j]) {
j = next[j];
}
// 相同的个数
if (str[i] == str[j]) {
j++;
}
next[i+1] = j;
} return next;
} // 另一种写法
// vector<int> getNext2(string str) {
// int j = 0;
// int i = 1;
//
// vector<int> next(str.size());
// next[0] = 0; // 必须是0
//
// while (i < str.size()) {
// if (str[i] == str[j]) {
// j++;
// next[i] = j;
// i++;
// }
// else {
// if (j != 0) {
// j = next[j - 1];
// }
// else { // j 为 0
// next[i] = 0;
// i++;
// }
// }
// }
//
// return next;
//
// } int search(string original, string find, vector<int> next) {
int i = 0, j = 0;
for (i = 0; i < original.length(); ++i) {
while (j > 0 && original[i] != find[j]) {
j = next[j];
}
if (original[i] == find[j])
++j;
if (j == find.size()) {
return i - j + 1;
}
} return -1;
} int main(int argc, const char * argv[]) {
string o = "ABABACAAC";
string f = "ABABACA"; vector<int> next = getNext(f);
// next
int i = 1;
while (i < next.size()) {
cout << "next " << next[i] << endl;
i++;
} //search
int result = search(o, f, next);
cout << "result " << result << endl; return 0;
}

KMP 理解的更多相关文章

  1. POJ3450【KMP理解】

    题意: 求多个字符串的最长公共子串 思路: 4000个串,200长度. 一种暴力,对于一个串最多有200*200=40000级别个子串,然后我要再处理一下next数组200,8e6复杂度: 然后我要和 ...

  2. 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)

    题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...

  3. KMP高质量代码实现详解

    KMP算法 对于KMP算法我分为两个部分说明,第一部分是算法部分,介绍KMP算法的算法思想:第二部分是实现部分,介绍一种厉害的实现代码以及代码注释.当然了由于本文主要介绍怎么实现故而先分析实现,对KM ...

  4. BZOJ 3670 NOI2014 动物园 KMP+dp

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3670 题意概述:令num[i]表示字符串由1~i的字符形成的前缀中不相重叠的相同前后缀的数 ...

  5. 算法之美--3.2.3 KMP算法

    不知道看了几遍的kmp,反正到现在都没有弄清楚next[j]的计算和kmp的代码实现,温故而知新,经常回来看看,相信慢慢的就回了 从头到尾彻底理解KMP 理解KMP /*! * \file KMP_算 ...

  6. 初涉KMP算法

    久仰字符串系列理论 KMP 讲解(引用自bzoj3670动物园) 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有 ...

  7. 【BZOJ】【1009】 【HNOI2008】GT考试

    DP/KMP/矩阵乘法 好神的题啊……跪了跪了 $n\leq 10^9$是什么鬼……我们还是先不要考虑这个鬼畜的玩意了>_> 用类似数位DP的思路,我们可以想到一个DP方程:$f[i][j ...

  8. 从头到尾彻底理解KMP

    从头到尾彻底理解KMP 作者:July 时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进. 1. 引言 本KMP原文最初写于2年多前的201 ...

  9. 深入理解kmp中的next数组

    next数组 1. 如果对于值k,已有p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,相当于next[j] = k. 此意味着什么呢?究其本质,next[j] = ...

随机推荐

  1. 【codeforces】【比赛题解】#869 CF Round #439 (Div.2)

    良心赛,虽然我迟了半小时233333. 比赛链接:#869. 呃,CF的比赛都是有背景的……上次是<哈利波特>,这次是<物语>…… [A]巧妙的替换 题意: Karen发现了石 ...

  2. 41 - 数据库-pymysql41 - 数据库-pymysql-DBUtils

    目录 1 Python操作数据库 2 安装模块 3 基本使用 3.1 创建一个连接 3.2 连接数据库 3.3 游标 3.3.1 利用游标操作数据库 3.3.2 事务管理 3.3.3 执行SQL语句 ...

  3. Linux嵌入式交叉编译环境 的搭建【转】

    转自:http://blog.csdn.net/woaixiaozhe/article/details/7395435 1. 安装标准的C开发环境,由于Linux安装默认是不安装的,所以需要先安装一下 ...

  4. Linux下简单粗暴使用rsync实现文件同步备份【转】

    这篇来说说如何安全的备份,还有一点不同的是上一篇是备份服务器拉取数据,这里要讲的是主服务器如何推送数据实现备份. 一.备份服务器配置rsync文件 vim /etc/rsyncd.conf #工作中指 ...

  5. MAVLink v1.0详解——结构

    本文针对 MAVLink v1.0版本,协议版本:3. MAVLink是为微型飞行器MAV(Micro Air Vehicle)设计的(LGPL)开源的通讯协议.是无人飞行器和地面站(Ground C ...

  6. Scrapy命令行工具简介

    Windows 10家庭中文版,Python 3.6.4,virtualenv 16.0.0,Scrapy 1.5.0, 在最初使用Scrapy时,使用编辑器或IDE手动编写模块来创建爬虫(Spide ...

  7. lumen 在AppServiceProvider 使用Illuminate\Support\Facades\Redis 报错

    这里需要注意 bootstrap/app.php中AppServiceProvider 和RedisServiceProvider 注入的先后顺序

  8. 【前端】上拉加载更多dropload.min.js的使用

    代码如下:入职代码修改接口及html为自己的即可(下面主要展示js部分) <!DOCTYPE html><html> <head> <meta charset ...

  9. 数据科学实战手册(R+Python)书中引用资料网址

    本文会持续将<数据科学实战手册(R+Python)>一书中的附带参考资料网址手打出来, 方便访问. 由于书中的参考资料网址太多, 这个文档将可能花费一段时间才能完成. 第一章 P7  Rs ...

  10. 【笔记】jQuery插件开发指南

    原文链接:http://www.cnblogs.com/Wayou/p/jquery_plugin_tutorial.html (有部分增删和修改) jQuery插件开发模式 软件开发过程中是需要一定 ...