KMP算法的详细解释及实现
这是我自己学习算法时有关KMP的学习笔记,代码注释的十分的详细,分享给大家,希望对大家有所帮助 在介绍KMP算法之前,
先来介绍一下朴素模式匹配算法:
朴素模式匹配算法:
假设要从主串S=”goodgoole”中找到T=”google”这个字串的位置,我们需要一下的步骤:
1,主串S的第一位开始,S与T的前三个字母都能成功匹配,但是S的第四个字母是d,而T的第四位是g,所以主串S的第一位匹配失败
2,然后从主串的第二位开始,会发现主串的第二位字母与T的第一位字母不同,所以匹配失败,然后再从主串的第三位开始,
3,经过这样的依次尝试后,之到主串的第五位开始,S与T的6个字母完全匹配成功
该朴素模式匹配算法的代码实现是:
该算法的功能是返回字串T在主串S中第pos个字符之后的位置,若不存在,则函数返回值为0,前提是T非空且1<pos<StrLength(S)
int Index(char* S,char* T,int pos)//index是索引的意思
{
int i=pos-1;//i用于主串S中当前位置的下标,S[0]是主串T的第一个字符
int j=0;//j用于子串T中当前位置下标值,即T[0]是字串T的第一个字符
while(i<strlen(S)&&j<strlen(T))
{
if(S[i]==T[j])//如果主串S当前的字母与子串的字母相等则继续
{
++i;
++j;
}
else
{
i=i-j+1;//eg:如果第一次匹配时,不相等则使i=i-j+2=i+1;即向下走一个字母,以i=0为例,刚开始从主串第一个位置开始,如果S[i]==T[j]一直满足,则i和j同步变化,即i=j;一旦有不相等的字母时,i=i-j+1,实际就是i=1;然后再从主串的第二个字母开始
j=0;//重新匹配时,j又回到T的子串的首位
}
}
if(j==strlen(T))//此时已完成匹配
return i-strlen(T);//返回
else
return 0;
}
KMP模式匹配算法
KMP算法中把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度;
next数组值得推导:
T="abcdex";(前后缀一个字符相等,k值是2,两个字符相等,k值是3,n个k值相等k值就是就是n+1)
1,当j=1时,next[1]=0;
2,当j=2时,j由1到j-1只有字符"a",next[2]=1;
3,当j=3时,j由1到j-1就只有字符串"ab",显然"a"与"b"不相等,所以next[3]=1;
4,同理得:T串的next[j]为011111;
T="ababaaaba";
1,当j=1时,next[1]=0;
2,当j=2时,next[2]=1;
3,当j=3时,next[3]=1;
4,当j=4时,next[4]=2;//j由1到j-1的串是"aba",前缀字符"a"与后缀字符"a"相等,next[4]=2;
5,当j=5时,next[5]=3;//串是"abab",前缀是"ab",后缀是"ab",有两个相同的字符,所以为3
6,当j=6时,next[6]=4;//串是"ababa",前缀是"aba",后缀是"aba",有三个相同的字符,所以为4
7,当j=7时,next[7]=2;//串是"ababaa",前缀字符是"a"与后缀字符"a"相等,有两个相同的字符,所以为2
8,当j=8时,next[8]=2;//串是"ababaaa",前缀字符是"a"与后缀字符"a"相等,有两个相同的字符,所以为2
9,当j=9时,next[9]=3;//串是"ababaaab",前缀字符是"ab",后缀字符也为"ab",有两个相同的字符,所以为3
10,当j=10时,next[10]=4;//串是"ababaaaba",前缀字符是"aba",后缀字符也为"aba",有三个相同的字符,所以为4
KMP模式匹配算法实现
1,通过计算返回子串T的next数组
void get_next(char* T,int *next)
{
int i,j;
i=1;
j=0;
next[1]=0;
while(i<=strlen(T))
{
if(j==0||T[i-1]==T[j-1])
{
++i;
++j;
next[i]=j;
}//以T="abcdex"为例:该循环的执行顺序:第一步,j=0,执行,(i=2,j=1,next[2]=1)第二步,不符合循环条件,j=next[1]=0,j又变为0为了再次进入循环,(i=3,j=1,next[3]=1)依次往下循环
else
j=next[j];
}
}
//这段代码的目的就是为了计算出当前要匹配的串T的next数组
int Index_KMP(char* S,char* T,int pos)
{
int i=pos;
int j=1;
int next[255];
get_next(T,next);
while(i<=strlen(S)&&j<=strlen(T))
{
if(j==0||S[i-1]==T[j-1])
{
++i;
++j;
}
else
j=next[j];//起到回溯的作用
}
if(j>strlen(T))
return (i-strlen(T)-1);
else
return -1;
}
附加一个实例:
#include<iostream>
using namespace std;
void get_next(char* T,int *next)
{
int i,j;
i=1; j=0;
next[1]=0;
while(i<=strlen(T))
{
if(j==0||T[i-1]==T[j-1])
{
++i;
++j;
next[i]=j;
}//以T="abcdex"为例:该循环的执行顺序:第一步,j=0,执行,(i=2,j=1,next[2]=1)第二步,不符合循环条件,j=next[1]=0,j又变为0为了再次进入循环,(i=3,j=1,next[3]=1)依次往下循环
else
j=next[j];
}
}//这段代码的目的就是为了计算出当前要匹配的串T的next数组
int Index_KMP(char* S,char* T,int pos)
{
int i=pos;
int j=1;
int next[255];
get_next(T,next);
while(i<=strlen(S)&&j<=strlen(T))
{
if(j==0||S[i-1]==T[j-1])
{
++i;
++j;
}
else
j=next[j];//起到回溯的作用
}
if(j>strlen(T))
return (i-strlen(T)-1);
else
return -1;
}
int main()
{
char* T="bc";
char* S="babaacbababcbababcbcbc";
int pos=1;
int next[255];
get_next(T,next);
for(int j=1;j<=2;j++)
cout<<"j="<<j<<":"<<"next"<<"["<<j<<"]"<<next[j]<<endl;
cout<<"子串T在主串S第"<<pos<<"个字符之后的第"<<Index_KMP(S,T,pos)<<"个位置"<<endl;
return 0;
}
KMP算法的详细解释及实现的更多相关文章
- KMP算法的详细解释
什么是kmp算法呢?这是一个处理字符串的算法,用来判断给出的模式串p是否存在于文本串t中(p的长度小于t). 在本文中,字符串储存在字符数组中,并且第一个字符放在下标为1的元素中. 那么如何理解kmp ...
- C语言实现数组快速排序(含对算法的详细解释)
/* 说明: 代码参考过网上代码,但分析为个人原创,本贴重在说明快速排序算法的思想和运行过程. */ 代码部分: #include<stdio.h> #include<stdlib. ...
- KMP算法原理
前几天在看数据结构与算法,里面提到过kmp算法,一个超级经典的字符串匹配算法.虽然网上有一大堆关于kmp算法的介绍文章,但是我看过之后还是“不明觉厉”.所以打算自己写写,大家一起学习吧. 一.关于KM ...
- 字符串模式匹配之KMP算法的next数组详解与C++实现
相信来看next数组如何求解的童鞋已经对KMP算法是怎么回事有了一定的了解,这里就不再赘述,附上一个链接吧:https://www.cnblogs.com/c-cloud/p/3224788.html ...
- 【数据结构&算法】10-串基础&KMP算法源码
目录 前言 串的定义 串的比较 串的抽象类型数据 串与线性表的比较 串的数据 串的存储结构 串的顺序存储结构 串的链式存储结构 朴素的模式匹配算法 模式匹配的定义 朴素的匹配方法(BRUTE FORC ...
- 22.1.22 并查集和KMP算法
22.1.22 并查集和KMP算法 1.并查集结构 1)实现: 并查集有多种实现方式,例如向上指的图的方式,数组的方式等等.其根本思想就在于准确记录某个节点的根节点,这个这种记录就能够很快的实现并查集 ...
- KMP算法具体解释(转)
作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解 ...
- KMP算法详细分解
1. 引言 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的 ...
- (收藏)KMP算法的前缀next数组最通俗的解释
我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性, ...
随机推荐
- BOOL和bool的区别
一. 1.类型不同 BOOL为int型 bool为布尔型 2.长度不同 bool只有一个字节 BOOL长度视实际环境来定,一般可认为是4个字节 3.取值不同 bool取值false和true,是0和1 ...
- Linux学习 : 自己写bootloader
一.bootloader 目标:启动内核 基本功能: ①初始化硬件:关看门狗.设置时钟.设置SDRAM.初始化NAND FLASH ②image比较大需要重定位到SDRAM ②将内核从NAND FLA ...
- java多线程总结
java中的多线程 一般来说,当运行一个应用程序的时候,就启动了一个进程,当然有些会启动多个进程.启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的.在进程 ...
- web 页面上纯js实现按钮倒计数功能
需求构思:本功能想实现的是,一个按钮在页面载入就显示提醒续费,,,倒数60秒后,完成提醒功能,可以按另外一个页面跳转到主页. 参考网上的大神,实现如下:Button2倒数,Button3跳转,在页面上 ...
- 总结-css编码规范
一.注释 统一采用 :/* 注释内容 */ 二.命名 1.常用命名(多查单词) 参考命名规范.doc 2.选择器 1> [建议] 选择器的嵌套层级应不大于 3 级,位置靠后的限定条件应尽可能精确 ...
- restful
根据名称对应 相当于换了别名(很无聊)
- vim笔记2
用vim 快两年了 看过教程也不少,总的来说还是得自己多练习,当自己觉得有需要的时候,再添加功能.这里分享个看过的最好的教程,出自贴吧的某个朋友,写的很好 零 学会盲打 壹 配置文件先从最简开始,在 ...
- What is the DD in java web application
http://docs.oracle.com/cd/E13222_01/wls/docs70/webapp/webappdeployment.html
- MySQL中的while、repeat、loop循环
循环一般在存储过程和存储函数中使用频繁,这里只给出最简单的示例 while delimiter $$ create procedure test_while() begin declare sum i ...
- WordPress博客平台的搭建--基于Ubuntu14服务器
环境:阿里云服务器,系统Ubuntu14.04, 阿里云域名 大致流程:LNMP+WordPress 主要参考博客:VPS+LNMP+WordPress搭建个人网站/博客 遇到的问题: 1.在登陆域名 ...