理解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接下来讨论的全部是真前缀 ...
随机推荐
- USACO Section 2.2: Preface Numbering
搬了leetcode的代码 /* ID: yingzho1 LANG: C++ TASK: preface */ #include <iostream> #include <fstr ...
- GitHub 教程 in Ubuntu
Follow these steps to configure github if you are the first time to use Github 1. Sign up a username ...
- Git忽略文件方法【转】
转自:http://www.cnblogs.com/shangdawei/archive/2012/09/08/2676669.html http://cwind.iteye.com/blog/166 ...
- asp.net mvc4使用百度ueditor编辑器
原文 http://www.cnblogs.com/flykai/p/3285307.html 已测试 相当不错 前言 配置.net mvc4项目使用ueditor编辑器,在配置过程中遇见了好 ...
- 选错实施顾问公司 ERP项目九死一生
今天接到一个朋友的电话,他是一家企业老总.这位老总感到非常头疼的是他的企业选择了一款国际上名气很大的ERP软件,但实施效果却强差人意.他的疑问是"不是说只要选对了ERP产品,谁实施都能成功吗 ...
- 爬虫技术(四)-- 简单爬虫抓取示例(附c#代码)
这是我的第一个爬虫代码...算是一份测试版的代码.大牛大神别喷... 通过给定一个初始的地址startPiont然后对网页进行捕捉,然后通过正则表达式对网址进行匹配. List<string&g ...
- How to use 'crontab' command on bitnami
You can edit the cron file using the following command: $ sudo crontab -e You can add a new line lik ...
- POJ 1944 - Fiber Communications
原题地址:http://poj.org/problem?id=1944 题目大意:有n个点排成一圈,可以连接任意两个相邻的点,给出 p 对点,要求这 p 对点必须直接或间接相连,求最少的连接边数 数据 ...
- Large Object Heap内存碎片在.NET 4.5中的改进
.NET 4.5已然到来,预览了解了下Large Object Heap在.NET 4.5中的效能改进.借此和大家来探讨下.本文不讨论Loder Heap,SOH(samll object heap) ...
- CSS选择符类型
一.标签选择符:针对某一类标签,可以以标签作为选择符 <style type="text/css"> p{color:#F00; font-size:36px;} &l ...