理解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接下来讨论的全部是真前缀 ...
随机推荐
- javascript QUnit 单元测试
<!doctype html> <html> <head lang="zh-CN" dir="ltr"> <meta ...
- json 字符串转换成对象,对象转换成json字符串
json 字符串转换成对象,对象转换成json字符串 前端: 方法一: parseJSON方法: [注意jquery版本问题] var str = '{"name":&qu ...
- 展讯NAND Flash高级教程【转】
转自:http://wenku.baidu.com/view/d236e6727fd5360cba1adb9e.html 展讯NAND Flash高级教程
- 《Linux/Unix系统编程手册》读书笔记5
<Linux/Unix系统编程手册>读书笔记 目录 第8章 本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/g ...
- 总结Selenium自动化测试方法(四)WebDriver常用的操作
四.WebDriver常用的操作 1.控制浏览器操作 #控制浏览器的大小 self.driver.set_window_size(480,800) #控制浏览器返回 self.driver.back( ...
- Android开发之PopupWindow
/* * Android开发之PopupWindow * * Created on: 2011-8-8 * Author: blueeagle * Email: liujiaxiang@g ...
- 【转】PWM占空比和分辨率
占空比是接通时间与周期之比冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同占空比:就是输出的PWM中,高电平保持的时间与该PWM的时钟周期的时间之比,如一个PWM的频率是1000Hz, ...
- Spring MVC详细运行流程
- Mvc 自带分页控件PagedList.Mvc Demo示例
添加/下载PagedList.Mvc 直接搜索mvc pagelist 就会出来.安装完成即可.在项目的packages文件夹下面就会出现PagedList.Mvc.4.5.0.0 和PagedLis ...
- HDU 4006 The kth great number【优先队列】
题意:输入n行,k,如果一行以I开头,那么插入x,如果以Q开头,则输出第k大的数 用优先队列来做,将队列的大小维护在k这么大,然后每次取队首元素就可以了 另外这个维护队列只有k个元素的时候需要注意一下 ...