理解KMP
//简单的字符串匹配算法 #include <iostream> using namespace std; int Index_BF(char s[], char T[], int pos)
{
int i = pos, j = ;
while (s[i+j]!='\0'&&T[j]!='\0')
{
if (s[i+j]==T[j])
{
j++; //继续比较后一字符
}
else
{
i++;
j = ; //重新开始新一轮的匹配
}
}
if (T[j] == '\0')
{
return i; //匹配成功返回下标
}
else
return -; //串s中(第pos个字符起)不存在和串T相同的子串
} int matchString(const string& target,const string& pattern)
{
int target_size = target.size();
int pattern_size = pattern.size();
int target_index = ;
int pattern_index = ;
if (target_size<=||pattern_size<=||target_size<pattern_size)
{
return -;
}
while (target_index<target_size&&pattern_index<pattern_size)// 不能有等于号
{
if (target[target_index]==pattern[pattern_index])
{
target_index++;
pattern_index++;
}
else
{
target_index = target_index - pattern_index + ; //当前标志-匹配的长度+1
pattern_index = ;
}
}
if (pattern_index==pattern_size&&target_index<=target_size)
{
return target_index - pattern_size ;
}
else
{
return -;
}
} int main()
{
cout << "第一种方法:" << Index_BF("banananobano", "nano", ) << endl; cout << "第二种方法:"<<matchString("banananobano", "nano")<<endl; return ;
}
下标
|
0
|
1
|
2
|
3
|
4
|
T
|
a
|
b
|
c
|
a
|
c
|
next
|
-1
|
0
|
0
|
-1
|
1
|
下标
|
0
|
1
|
2
|
3
|
4
|
T
|
a
|
b
|
c
|
a
|
b
|
next
|
-1
|
0
|
0
|
-1
|
0
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
T
|
a
|
b
|
a
|
b
|
c
|
a
|
a
|
b
|
c
|
next
|
-1
|
0
|
-1
|
0
|
2
|
-1
|
1
|
0
|
2
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
T
|
a
|
b
|
C
|
a
|
b
|
C
|
a
|
d
|
next
|
-1
|
0
|
0
|
-1
|
0
|
0
|
-1
|
4
|
下标
|
0
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
T
|
a
|
d
|
C
|
a
|
d
|
C
|
a
|
d
|
next
|
-1
|
0
|
0
|
-1
|
0
|
0
|
-1
|
0
|
void get_nextval(const char *T, int next[])
{
// 求模式串T的next函数值并存入数组 next。
int j = , k = -;
next[] = -;
while (T[j] != '/0')
{
if (k == - || T[j] == T[k])
{
++j;
++k;
if (T[j] != T[k])
next[j] = k;
else
next[j] = next[k];
}// if
else
k = next[k];
}// while } //下面是KMP模式匹配程序 int KMP(const char *Text, const char* Pattern) //const 表示函数内部不会改变这个参数的值。
{
if (!Text || !Pattern || Pattern[] == '\0' || Text[] == '\0')//
return -;//空指针或空串,返回-1。
int len = ;
const char *c = Pattern;
while (*c++ != '\0')//移动指针比移动下标快。
++len;//字符串长度。
int *next = new int[len + ];
get_nextval(Pattern, next);//求Pattern的next函数值
int index = , i = , j = ;
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
delete[]next;
if (Pattern[j] == '\0')
return index;// 匹配成功,返回匹配首字符下标
else
return -;
}
//测试程序: int main()
{
char* text = "abcdefgh123456789465asdac789asd4654qw5e46a1";
char*pattern = "4654qw";
int pos = KMP(text, pattern);
if (pos == -)
printf("无法找到匹配字符串!\n");
else
printf("匹配成功!匹配首字符下标:%d\n", pos);
system("pause");
return ;
}
int kmp_find(const string& target,const string& pattern)
{
const int target_length = target.size();
const int pattern_length = pattern.size();
int* overlay_value = new int[pattern_length];
int index;
overlay_value[] = -;
for (int i = ; i < pattern_length; i++)
{
index = overlay_value[i - ]; //存储先前匹配失败的位置
while (index >= && pattern[i] != pattern[index + ]) // pattern[i]!=pattern[index+1]
{
index = overlay_value[index]; //
}
if (pattern[i] == pattern[index + ])
{
overlay_value[i] = index + ;
}
else
{
overlay_value[i] = -;
}
}
//匹配算法
int pattern_index = ;
int target_index = ;
while (pattern_index<pattern_length&&target_index<target_length)
{
if (target[target_index]==pattern[pattern_index])
{
++target_index;
++pattern_index;
}
else if (pattern_index==)
{
++target_index;
}
else
{
pattern_index = overlay_value[pattern_index - ] + ;
}
}
if (pattern_index == pattern_length)
{
return target_index - pattern_index;
}
else
return -;
delete[] overlay_value; } int main()
{
string source = "annbcdanacadsannannabnna";
string pattern = "annacanna";
cout << "第一种方法:" << Index_BF("banananobano", "nano", ) << endl; cout << "第二种方法:" << matchString(source, pattern) << endl; cout << "kmp:" << kmp_find(source,pattern) << endl;;
string pattern1 = "abaabcaba";
compute_overlay(pattern1); return ;
}
参考:http://blog.csdn.net/caoyan_12727/article/details/52556327
理解KMP的更多相关文章
- 从头到尾彻底理解KMP
从头到尾彻底理解KMP 作者:July 时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进. 1. 引言 本KMP原文最初写于2年多前的201 ...
- 转:[置顶] 从头到尾彻底理解KMP(2014年8月22日版)
[置顶] 从头到尾彻底理解KMP(2014年8月22日版)
- 【转】从头到尾彻底理解KMP
很好,讲得很清晰,值得学习. 作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个月从早到晚不断改进. 1. 引言 本KMP原文最初写于2年多前的 ...
- 【July】从头到尾彻底理解KMP
从头到尾彻底理解KMP 作者:July时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进. 1. 引言 本KMP原文最初写于2年多前的2011 ...
- 理解 KMP 算法
KMP(The Knuth-Morris-Pratt Algorithm)算法用于字符串匹配,从字符串中找出给定的子字符串.但它并不是很好理解和掌握.而理解它概念中的部分匹配表,是理解 KMP 算法的 ...
- 从头到尾测地理解KMP算法【转】
本文转载自:http://blog.csdn.net/v_july_v/article/details/7041827 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP ...
- 【转载】从头到尾彻底理解KMP
转自:http://blog.csdn.net/v_july_v/article/details/7041827 从头到尾彻底理解KMP 作者:July 时间:最初写于2011年12月,2014年7月 ...
- 深入理解kmp中的next数组
next数组 1. 如果对于值k,已有p0 p1, ..., pk-1 = pj-k pj-k+1, ..., pj-1,相当于next[j] = k. 此意味着什么呢?究其本质,next[j] = ...
- 理解KMP算法
母串:S[i] 模式串:T[i] 标记数组:Next[i](Next[i]表示T[0~i]最长前缀/后缀数) 先来讲一下最长前缀/后缀的概念 例如有字符串T[6]=abcabd接下来讨论的全部是真前缀 ...
随机推荐
- Android NDK 和 OpenCV 整合开发总结(3)
Android NDK 和 OpenCV 整合开发总结(3) http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-open ...
- iPhone(iOS设备) 无法更新或恢复时, 如何进入恢复模式
在更新或恢复 iPhone 时,如果遇到以下所列问题之一.可能就要将设备置于恢复模式,并尝试重新恢复设备. 设备不断地重新启动,但从未显示主屏幕. 无法完成更新或恢复,且 iTunes 不再能识别设 ...
- 总结Selenium自动化测试方法(六)常见的异常错误处理
六.常见的异常错误处理 NoSuchElementException: Message: Unable to locate element: {"method":"xpa ...
- Jquery-json
第三方插件: jquery.json-2.4.js Jquery-json 是 jQuery 的一个插件,可轻松实现对象和 JSON 字符串之间的转换.可序列化 JavaScript 对象.数值.字符 ...
- zoj 3329 One Person Game (有环 的 概率dp)
题目链接 这个题看的别人的思路,自己根本想不出来这种设方程的思路. 题意: 有三个骰子,分别有k1,k2,k3个面. 每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和. 当 ...
- HDU 3863 (博弈) No Gambling
这是我见过的最简单的一道博弈了,其实不要被复杂的棋盘吓到了. 首先肯定会有而且仅有一个人胜,而且因为棋盘是对称的,所以先手相对于后手肯定更有优势,那么肯定是先手赢. 这是不是严格的推理,但是确实比较容 ...
- (转)IOS UITableView学习
转自:http://www.cnblogs.com/smileEvday/archive/2012/06/28/tableView.html 作者:一片枫叶 看TableView的资 ...
- 利用matlab编写实现显示fmri切片slice图像 混合显示 不同侧面显示 可叠加t检验图显示 by DR. Rajeev Raizada
1.参考 reference 1. tutorial主页:http://www.bcs.rochester.edu/people/raizada/fmri-matlab.htm. 2.speech_b ...
- 【转】vim - tab变空格
vim中将tab自动转换成空格 在vim中,有时需要将tab转换成space.使用ret命令(replace tab).[range]ret[ab]! [new-tabstop] 举例:将第一行到文件 ...
- Ant编译环境
使用ant编译有关于C compiler(cc task)的时候,需要确认vs的环境有无配置, 否则会遇到形形色色的问题,比如各种 vs编译工具找不到的错误, 一个比较简单的解决方案,就是在执行ant ...