算法 kmp算法
kmp算法是改进后的字符匹配算法,它与bf算法的区别是,每次从串与主串匹配失败后,从串与主串匹配的位置不同。
下面具体说下这两种算法的区别:
主串:BABCDABABCDABCED
从串:ABCDABCED
BF算法:
第一步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A |
从主串的第一个字符位置开始与从串第一个字符位置进行匹配,匹配失败
第二步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A | B | C | D | A | B | C |
从主串的第二个字符位置开始与从串第一个字符位置进行匹配,匹配失败
第三步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A |
从主串的第三个字符位置开始与从串第一个字符位置进行匹配,匹配失败
...........
第七步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A |
从主串的第七个字符位置开始于从串第一个字符位置进行匹配,匹配失败
第八步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A | B | C | D | A | B | C | E | D |
匹配成功,这个就是BF算法,每次匹配失败后要从主串的下一个字符位置与从串的第一个字符接着进行匹配。
kmp算法:
第一步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A |
主串与从串的第一个字符不匹配
第二步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A | B | C | D | A | B | C |
第三步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A | B | C |
这里就和bf不一样了,其原因就是从串中字符有相同的一部分(AB),这里先知道区别,待会我会说它的实现过程
第四步:
| B | A | B | C | D | A | B | A | B | C | D | A | B | C | E | D |
| A | B | C | D | A | B | C | E | D |
如果看不懂的话,下面会讲清楚,然后根据程序找下标就可以知道原因了。
kmp算法分两部分:①next数组(kmp算法的核心)
②字符串的匹配
在讲解next数组时,顺便把前缀和后缀的知识也说了。
比如上面的从串:ABCDABCED(前缀是从第一个字符数,但后缀不是倒着数,它也是顺着数,看下面的写法吧)
第一个字符前,它没有串,所以没有前缀和后缀,则它也没有最长长度,我把它的长度初始化为0。
第二个字符前,它的串是A,前缀和后缀是不能包含串本身,所以它没有前缀和后缀,长度为0。
第三个字符前,它的串是AB,前缀是A,后缀是B,不匹配,长度为0。
第四个字符前,它的串是ABC,第一种,前缀是A,后缀是C,不匹配,长度为0,
第二种,前缀是AB,后缀是BC,不匹配,长度为0,
所以最长长度为0。
第五个字符前,它的串是ABCD,第一种,前缀是A,后缀是D,不匹配,长度为0,
第二种,前缀是AB,后缀是CD,不匹配,长度为0,
第三种,前缀是ABC,后缀是BCD,不匹配,长度为0,
所以最长长度为0。
第六个字符前,它的串是ABCDA,第一种,前缀是A,后缀是A,匹配,长度为1,
第二种,前缀是AB,后缀是DA,不匹配,长度为0,
第三种,前缀是ABC,后缀是CDA,不匹配,长度为0,
第四种,前缀是ABCD,后缀是BCDA,不匹配,长度为0,
所以最长长度为1。
第七个字符前,它的串是ABCDAB,第一种,前缀是A,后缀是B,不匹配,长度为0,
第二种,前缀是AB,后缀是AB,匹配,长度为2,
第三种,前缀是ABC,后缀是DAB,不匹配,长度为0,
第四种,前缀是ABCD,后缀是CDAB,不匹配,长度为0,
第五种,前缀是ABCDA,后缀是BCDAB, 不匹配,长度为0,
所以最长长度为2。
第八个字符前,它的串是ABCDABC,第一种,前缀是A,后缀是C,不匹配,长度为0,
第二种,前缀是AB,后缀是BC,不匹配,长度为0,
第三种,前缀是ABC,后缀是ABC,匹配,长度为3,
第四种,前缀是ABCD,后缀是DABC,不匹配,长度为0,
第五种,前缀是ABCDA,后缀是CDABC,不匹配,长度为0,
第六种,前缀是ABCDAB,后缀是BCDABC,不匹配,长度为0,
所以最长长度为3。
第九个字符前,它的串是ABCDABCE,第一种,前缀是A,后缀是E,不匹配,长度为0,
第二种,前缀是AB,后缀是CE,不匹配,长度为0,
第三种,前缀是ABC,后缀是BCE,不匹配,长度为0,
第四种,前缀是ABCD,后缀是ABCE,不匹配,长度为0,
第五种,前缀是ABCDA,后缀是DABCE,不匹配,长度为0,
第六种,前缀是ABCDAB,后缀是CDABCE,不匹配,长度为0,
第七种,前缀是ABCDABC,后缀是BCDABCE,不匹配,长度为0,
所以最长长度为0。
然后根据我们求出来的最长长度,就能绘制出next表了,
| 下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| 从串 | A | B | C | D | A | B | C | E | D |
| next | 0 | 0 | 0 | 0 | 0 | 1 | 2 | 3 | 0 |
| 下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| 从串 | A | B | C | D | A | B | C | E | D |
| next | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 0 |
第二个B与第一个B的next值一样为0,第二个C与第一个C的next值一样为0。
这就是next数组及其改进后的next数组。
next数组程序:
void Get_next(int *next, string s2)
{
int i = 1;
int j = 0;
next[i] = 0;
while(i <= s2.length())
{
if(j == 0 || s2[i - 1] == s2[j - 1])
{
i++;
j++;
if(s2[i - 1] == s2[j - 1])
next[i] = next[j];
else
next[i] = j - 1;
}
else
j = next[j];
}
}
如果你理解了next数组的求值方法,根据bf算法的思路应该可以写出kmp字符匹配函数,
下面是kmp算法的总体程序:
#include <iostream>
#include <string>
using namespace std;
//求next数组下标
void Get_next(int *next, string s2)
{
int i = 1;
int j = 0;
next[i] = 0;
while(i <= s2.length())
{
if(j == 0 || s2[i - 1] == s2[j - 1])
{
i++;
j++;
if(s2[i - 1] == s2[j - 1])
next[i] = next[j];
else
next[i] = j - 1;
}
else
j = next[j];
}
// for(int k = 1; k < 10; k++)
// cout << next[k] << endl;
}
//匹配部分
int kmp(string s1, string s2, int pos)
{
int next[100];
Get_next(next, s2);
int i = 0;
int j = 0;
while(i < s1.length() && j < s2.length())
{
if(j == 0 || s1[i] == s2[j])
{
i++;
j++;
}
else
{
j = next[j + 1];
}
}
if(j >= s2.length())
return i - s2.length();
return -1;
}
int main()
{
string s1= "babcdababcdabced";
string s2 = "abcdabced";
int pos;
cin >> pos;
cout << kmp(s1, s2 ,pos) << endl;
return 0;
}
本程序只是个人的想法和思路,若有错误还请大家提出,若有不明白的地方,请在下面评论,谢谢大家啦!
对了,我的算法应该存在问题,希望多多指出。
算法 kmp算法的更多相关文章
- 数据结构与算法--KMP算法查找子字符串
数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...
- 经典算法 KMP算法详解
内容: 1.问题引入 2.暴力求解方法 3.优化方法 4.KMP算法 1.问题引入 原始问题: 对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),如果 match 是 st ...
- 笔记-算法-KMP算法
笔记-算法-KMP算法 1. KMP算法 KMP算法是一种改进的字符串匹配算法,KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一 ...
- 值得花费一周研究的算法 -- KMP算法(indexOf)
KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...
- [C++] [算法] KMP算法
KMP串匹配算法是一个经典的算法. 传统BF算法是传统的字符串匹配算法.很好理解.叶实现.但时间复杂度太高. 本文将从字符串模式字符串被称为.为了匹配字符串被称为主弦. KMP配时能够少移动从串的位置 ...
- 程序员必会算法-KMP算法
KMP算法是一种优秀的字符串匹配算法,字符串匹配的常规算法是一步一步进行移位和比较操作,直至找到完全相匹配的字符串. 下面通过一个例子,为大家仔细说明KMP算法的使用和思路: 问题: 在字符串“DEA ...
- BF算法 + KMP算法
准备: 字符串比大小:比的就是字符串里每个字符的ASCII码的大小.(其实这样的比较没有多大的意义,我们关心的是字符串是否相等,即匹配等) 字符串的存储结构:同线性表(顺序存储+链式存储) 顺序存储结 ...
- 图解算法——KMP算法
KMP算法 解决的是包,含问题. Str1中是否包含str2,如果包含,则返回子串开始位置.否则返回-1. 示例1: Str1:abcd123def Str2:123d 暴力法: 从str1的第一个字 ...
- 字符串匹配算法——KMP算法
处理字符串的过程中,难免会遇到字符匹配的问题.常用的字符匹配方法 1. 朴素模式匹配算法(Brute-Force算法) 求子串位置的定位函数Index( S, T, pos). 模式匹配:子串的定位操 ...
随机推荐
- Angular 引入第三方框架方法(如Jquery,Bootstrap)
1.npm i jquery --save / npm i bootstrap --save 2.angular.json 引入路径 3.引入Jquery和Bootstrap的类型描述文件 ...
- C#生成缩略图,C#给图片添加水印
生成缩略图 #region 生成缩略图 /// <summary> /// 生成缩略图 /// </summary> /// <param name="orig ...
- Jmeter5.1.1创建一个http请求的压力测试
1.首先添加一个线程组,在线程组中,配置压力情况 2.然后在线程组中,添加取样器,添加http请求:配置web服务器协议(http/https).服务器名称或IP.端口号.请求方法.路径等参数 3.然 ...
- LeetCode 206. Reverse Linked List倒置链表 C++
Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5->4-> ...
- R开发环境搭建
1.准备集成开发环境(IDE) R语言在一个好的IDE工具上应用才能更好的发挥它的作用,目前使用的最多的R语言集成开发环境是R STUDIO,下载地址为:https://www.rstudio.com ...
- QAC静态测试配置及使用教程
使用前提:安装成功QAC软件. . 1.打开软件如上 . 2.file->Auto-Create-Project,出现如下所示对话框 1-工程名字 2-将要分析的代码路径 3-代码报告输出路径 ...
- Linux连接虚拟机及操作指令
Linux的安装(虚拟机环境)与基础配置 一.背景 本文介绍如何安装虚拟机VMware以及如果在虚拟机上安装Linux系统以及Linux安装完毕之后的基础配置 需要准备的东西有VMware以及Li ...
- linux7 安装 zlib依赖库 与安装python 3.6
Linux 安装zlib依赖库 进入src: cd /usr/local/src 下载zlib库: wget http://www.zlib.net/zlib-1.2.11.tar.gz 解压下载的t ...
- [转载]EF或LINQ 查询时使用IN并且根据列表自定义排序方法
原文地址:EF或LINQ 查询时使用IN并且根据列表自定义排序方法作者:李明川 EF和LINQ改变了原有的手写SQL时期的一些编码方法,并且增强了各数据库之间的移植性简化了开发时的代码量和难度,由于很 ...
- py2neo的使用(转)
转自:https://blog.csdn.net/sinat_26917383/article/details/79901207#24-%E7%B1%BB%E4%BC%BCset%E7%9A%84%E ...