母串:S[i]

模式串:T[i]

标记数组:Next[i](Next[i]表示T[0~i]最长前缀/后缀数)

先来讲一下最长前缀/后缀的概念

例如有字符串T[6]=abcabd接下来讨论的全部是真前缀/真后缀,也就是除去串自己本身之外的前缀/后缀

T[0]=a,此时前后缀都是a那么Next[0]=1

T[0~1]=ab,此时前缀为a,后缀为b两者不等因此Next[1]=0

T[0~2]=abc,此时前缀为a,ab,后缀为bc,c同上有Next[2]=0

T[0~3]=abca,此时前缀为a,ab,abc,后缀为bca,ca,a可以看到共同部分只有a因此Next[3]=1

T[0~4]=abcab,此时前缀为a,ab,abc,abca,后缀为bcab,cab,ab,b此时最长的公共部分为ab因此Next[4]=2

T[0~5]=abcabd,此时前缀为a,ab,abc,abca,abcab,后缀为bcabd,cabd,abd,bd,d无相等部分故Next[5]=0

说完前后缀的概念之后再来说说KMP的核心思想

例如S=abcabcabdabba,T=abcabd匹配时的情况如下

可以看到在S[5]的位置匹配失败,KMP的处理方式如下

说一下原因,在S[5]的位置匹配失败后直接用S[5]与T[2]去开始匹配,因为Next[5-1]也就是Next[4]=2,因此直接从T[2]重新开始匹配

原因很简单,既然Next[4]=2那么T[0~1]既可以与S[0~1]相等,也可以与S[3~4]相等,所以可以直接从T[2]开始,这也是KMP的精妙所在,不理解的可以自己写两个串试试。所以难点就在于Next数组的实现了,具体实现过程如下

这里只介绍了核心思想,原文比较详细请见:https://www.douban.com/note/321870890/

下面给出kuangbin大神的模板

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<vector>
#include<queue>
#include<iterator>
#include<vector>
#include<set>
#define dinf 0x3f3f3f3f
typedef long long ll;
//const int Max=(1<<16)+10;
using namespace std;
#define SIZE 100000005 const int N = ;
int m_next[N];
char S[N],T[N];
int slen, tlen; void getNext()
{
int j, k;
j = ; k = -; m_next[] = -;
while(j < tlen)
if(k == - || T[j] == T[k])
m_next[++j] = ++k;
else
k = m_next[k]; }
/*
返回模式串T在主串S中首次出现的位置
返回的位置是从0开始的。
*/
int KMP_Index()
{
int i = , j = ;
getNext(); while(i < slen && j < tlen)
{
if(j == - || S[i] == T[j])
{
i++; j++;
}
else
j = m_next[j];
}
if(j == tlen)
return i - tlen+;
else
return -;
}
/*
返回模式串在主串S中出现的次数
*/
int KMP_Count()
{
int ans = ;
int i, j = ; if(slen == && tlen == )
{
if(S[] == T[])
return ;
else
return ;
}
getNext();
for(i = ; i < slen; i++)
{
while(j > && S[i] != T[j])
j = m_next[j];
if(S[i] == T[j])
j++;
if(j == tlen)
{
ans++;
j = m_next[j];
}
}
return ans;
}
int main()
{ int TT;
int i, cc;
string str;
cin>>TT;
while(TT--)
{
getchar(); scanf("%s %s",&T,&S);
slen = strlen(S);
tlen = strlen(T); cout<<"模式串T在主串S中首次出现的位置是: "<<KMP_Index()/+<<endl;
cout<<"模式串T在主串S中出现的次数为: "<<KMP_Count()<<endl;
}
return ;
}

理解KMP算法的更多相关文章

  1. 理解 KMP 算法

    KMP(The Knuth-Morris-Pratt Algorithm)算法用于字符串匹配,从字符串中找出给定的子字符串.但它并不是很好理解和掌握.而理解它概念中的部分匹配表,是理解 KMP 算法的 ...

  2. 深入理解KMP算法

    前言:本人最近在看<大话数据结构>字符串模式匹配算法的内容,但是看得很迷糊,这本书中这块的内容感觉基本是严蔚敏<数据结构>的一个翻版,此书中给出的代码实现确实非常精炼,但是个人 ...

  3. KMP算法详解 --- 彻头彻尾理解KMP算法

    前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k. 但是问题在于如何求出这个最大前后缀长度呢? 我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破, 后来翻看 ...

  4. 从头到尾测地理解KMP算法【转】

    本文转载自:http://blog.csdn.net/v_july_v/article/details/7041827 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP ...

  5. 深入理解KMP算法之续篇

    前言: 纠结于KMP已经两天了,相较于本人之前博客中提到的几篇博文,本人感觉这篇文章更清楚地说明了KMP算法的来龙去脉. http://www.cnblogs.com/goagent/archive/ ...

  6. 真正理解KMP算法

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4403560.html 所谓KMP算法,就是判断一个模式串是否是一个字符串的子串,通常的算法当 ...

  7. KMP算法 --- 深入理解next数组

    在KMP算法中有个数组,叫做前缀数组,也有的叫next数组. 每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符. 当然它描述的也是子串的对称程度,程度越高,值 ...

  8. 从有限状态机的角度去理解Knuth-Morris-Pratt Algorithm(又叫KMP算法)

    转载请加上:http://www.cnblogs.com/courtier/p/4273193.html 在开始讲这个文章前的唠叨话: 1:首先,在阅读此篇文章之前,你至少要了解过,什么是有限状态机, ...

  9. KMP算法的一次理解

    1. 引言 在一个大的字符串中对一个小的子串进行定位称为字符串的模式匹配,这应该算是字符串中最重要的一个操作之一了.KMP本身不复杂,但网上绝大部分的文章把它讲混乱了.下面,咱们从暴力匹配算法讲起,随 ...

随机推荐

  1. BZOJ2730——[HNOI2012]矿场搭建

    bzoj2730 & world final 2011 H 1.题目大意:就是有一个无向图,让你在里面选择点,使得,无论哪个点没了以后,其他的点都能到达你选择的任何一个点,输出最少 选择几个点 ...

  2. Webclent基本操作

    /** * @Title: webclientTest.java * @Package webclient * @Description: TODO(用一句话描述该文件做什么) * @author A ...

  3. MySQL重复数据

    delete from porn where Id not in (select minid from (select min(id) as minid from porn group by view ...

  4. git 忽略文件权限

    git config --add core.filemode false 发现.git/config 中新增了一行: [core] ... filemode = false ref: http://b ...

  5. centos终端中mysql中文显示乱码的处理

    http://stackoverflow.com/questions/3513773/change-mysql-default-character-set-to-utf-8-in-my-cnfhttp ...

  6. rest api设计的一般原则

    本文参考自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html,http://www.dongming8.cn/?p=590 服务器端: 1 ...

  7. 《oracle每天一练》Oracle冷备份与数据恢复

    相关帖子 转自http://blog.csdn.net/nsj820/article/details/5611361 备份 直接拷贝oracle目录下的admin.oradata(datafile,  ...

  8. SharePoint2010母版页想要的定制

    查找<div id="s4-ribbonrow" class="s4-pr s4-ribbonrowhidetitle"用style="disp ...

  9. poj4052

    题意:求一个文章(长度5.1e6)里面出现了多少个指定的模式串.重复出现只记一次.而且如果两个模式串都出现的情况下,一个是另一个的子串,则该子串不算出现过. 分析:AC自动机. 由于子串不算所以加一些 ...

  10. linux资源使用配置文件 /etc/security/limits.conf和ulimit

    limits.conf文件实际上是linux PAM中pam_limits.so的配置文件,而且只针对于单个会话. limits.conf的格式如下: <domain> <type& ...