理解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接下来讨论的全部是真前缀 ...
随机推荐
- socket的半包,粘包与分包的问题
http://zhaohuiopensource.iteye.com/blog/1541270 首先看两个概念: 短连接: 连接->传输数据->关闭连接 HTTP是无状态的,浏览器和 ...
- c# ComboBox特殊属性
c# ComboBox特殊属性 comboBox1.ValueMember = "Id"; 设置值 不显示的comboBox1.DisplayMember = " ...
- centos chrome
在centos6.X和redhat enterprise 中安装chrome,我找了很久都不行,今天终于找到了可以用下脚本那安装: #! /bin/bash # Google Chrome Insta ...
- GitPython git python 的开发库
工程地址: https://pypi.python.org/pypi/GitPython/需要安装先安装: gitdb https://pypi.python.org/pypi/gitdb GitPy ...
- pyhton小方法
import osa = os.walk('.') for i in a: print(i)
- jboss jndi配置部分参数详解
使用的是jboss7.1.1, jndi的配置在$JBOSS_HOME/standalone/configuration/standalone.xml中进行配置.配置jndi时有很多参数,解释下用到的 ...
- 【笨嘴拙舌WINDOWS】BMP图片浏览器
要将文件显示成图片这其中需要经过 1.将磁盘文件内容读取到内存: 2.将文件对应内存里包含的像素为以及像素信息转化为显示驱动器能理解的格式: 3.将转化过后的内存送到显卡的缓存区 4.显示器读取缓存现 ...
- memcached内存管理及key value长度限制
1)什么是内存碎片?内存是大小有限的资源.例如把内存比作一张小床,来了一个小伙伴,可以睡下,再来一个小伙伴也能睡下.现在两个人了,他们点了差不多的大小的位置(资源),位置还有剩下.然后再来一个小胖子, ...
- notebook笔记
启动 __main__.py 静态文件 static/ 模板 templates/ 路由 比如tree/handlers.py default_handlers WebSocket ws://loca ...
- redo和undo的区别
转摘:http://blog.163.com/jing_playboy/blog/static/757362222012520104521864/ redo--> undo-->dat ...