理解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接下来讨论的全部是真前缀 ...
随机推荐
- C# 数组、一维数组、二维数组、多维数组、锯齿数组
C# 数组.一维数组.二维数组.多维数组.锯齿数组 一.数组: 如果需要使用同一类型的对象,就可以使用数组,数组是一种数据结构,它可以包含同一类型的多个元素.它的长度是固定的,如长度未知的情况下,请 ...
- TCP连接探测中的Keepalive 和心跳包
采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是 ...
- (五)ASP.NET中动态生成控件
今天被问到如何在ASP.NET 页面中动态创建一批控件,并且希望在后续代码中能访问到这些动态创建的控件.我用下面的例子来解释这个问题 ================================= ...
- Docker入门命令
Edit Docker入门命令 # 安装镜像sudo docker pull ubuntu:12.04# 镜像列表sudo docker images# 运行镜像sudo docker run -t ...
- leetcode:Rotate List
Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...
- Windows 桌面软件:不绑定bing搜索的缤纷桌面
bing:世界上最好的壁纸提供商 ^.^一直垂涎着Bing的壁纸,总是想找机会来一番邂逅. 之前使用bing自家的缤纷桌面.这个软件缺点就是和bing搜索绑定太厉害,放在桌面上感觉那个黑色的条框很碍 ...
- BZOJ 1821 部落划分
kruskal.第k-1大的边. 其实prim会更快. #include<iostream> #include<cstdio> #include<cstring> ...
- POJ 2983 Is the Information Reliable? 信息可靠吗 (差分约束,spfa)
题意:有n个站排成一列,针对每个站的位置与距离关系,现有多个约束条件,约束条件分两种:(1)确定的.明确说明站a距离站b多少个单位距离.(2)不确定的.只知道a在b的左边至少1个单位距离. 根据已知 ...
- Python [Leetcode 344]Reverse String
题目描述: Write a function that takes a string as input and returns the string reversed. Example:Given s ...
- 中文分词系列(二) 基于双数组Tire树的AC自动机
秉着能偷懒就偷懒的精神,关于AC自动机本来不想看的,但是HanLp的源码中用户自定义词典的识别是用的AC自动机实现的.唉-没办法,还是看看吧 AC自动机理论 Aho Corasick自动机,简称AC自 ...