KMP算法研究(一)
2016-03-29 23:07
375 查看
变量定义:
T :主串W:模式串
next[i]:模式串中从第1个字符到第i+1个字符构成的子串的最大前缀后缀相等数目。
1.KMP算法简介
KMP算法主要是功能便是判断模式串是否出现在主串中,并找出相应的出现位置。而在常规的暴力破解算法中,通常采用顺序比对的方法进行查找,也就是将模式串依次与主串的第1、2、3....个字符比较,直到找出与模式串相等的子串,这样就会造成信息的浪费。而在KMP算法中,对于每一个模式串我们会事先计算出模式串的内部匹配信息,在匹配失败时最大的移动模式串,以减少匹配次数。2.KMP算法比较过程
假定主串T:a b a c a a ba c a b a
模式串M:a b a c a b
第一次比较:
T | a | b | a | c | a | a | b | a | c | a | b | a |
---|---|---|---|---|---|---|---|---|---|---|---|---|
M | a | b | a | c | a | b |
T | a | b | a | c | a | a | b | a | c | a | b | a |
---|---|---|---|---|---|---|---|---|---|---|---|---|
M | a | b | a | c | a | b |
T | a | b | a | c | a | a | b | a | c | a | b | a |
---|---|---|---|---|---|---|---|---|---|---|---|---|
M | a | b | a | c | a | b |
移动步数=上一步查找中相同的字符个数 -M中第一个不匹配字符的前一个字符的最大前缀后缀数
注解:
首先,前缀和后缀的解释如下
:
如:a
b a b a b c
后缀:通俗地说就是所有包含了尾部字符的字串,就是一个后缀,如c
,bc,abc,都是;
前缀:当然是包含了第一个字符的子串了.
其次,就是在步数的移动上。在上一步的比较中,假设相等的子串为:a b a c a,则该子串的最大前缀后缀数为1,也就是前缀与后缀相等时,最大的长度为1.也就是说,在主串中从i到i+4,在模式串中从0到4,是分别对应相等的,在下次的移动中,为了尽可能多地增大移动步数,就将模式串中移动到主串该次前缀的位置,重新开始比较。
具体实现代码如下:(时间很晚了,注释就明天起来再加)
#include<iostream> #include<string> using namespace std; void getNext(string W, int *next); void KMPsearch(string T,string W,int *next); int main(void){ int n = 0; string T,W; cin >> T; cin >> W; n = W.length(); int *next=new int ; getNext(W,next); KMPsearch(T,W,next); delete []next; return 0; } void KMPsearch(string T, string W, int *next){ int m = 0, n = 0, i = 0, j = 0; n = T.length(); m = W.length(); while (i < n){ if (T[i] != W[j] && j != 0){ i = i + j - next[j - 1]; j = 0; } if (T[i] != W[j] && j == 0){ i = i + 1; } if (T[i] == W[j]){ i++; j++; } if (j == m){ cout << "Location: " << i - m + 1<< endl; return; } } } void getNext(string W, int *next){ int m = W.length(); next[0] = 0; for (int i = 1; i < m; i++){ if (W[i] == W[next[i - 1]]){ next[i] = next[i - 1] + 1; } else{ next[i] = 0; } } /*for (int i = 0; i < m; i++){ cout << next[i] << endl; }*/ }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性