初学,理解可能不是那么准确~~
Next数组的含义:next[i]表示第0个元素到第i个元素组成的字符串的最大前缀后缀。Next[0]=0显然。
所以KMP的原理就是

通过找出每一阶段最大的相等的前缀后缀,那么匹配到某个字符失配时就可以从前缀的下一个字母开始匹配,而不用再回退匹配。使复杂度降从O(m^n)到O(m+n)。
最重要的就是求next数组,而且next数组在很多题都有应用,不止KMP。
而得到next数组的原理如下:

(画风就是这么洒脱,没办法~~~)
色的如图,如果比较到p,如果p点元素和q点元素相等,那么直接S1的长度加1就是next[q]了,即next[q]=next[q-1]+1。

但是如果不等,就要在S1中找到一个短一点的字符串,如棕色的那段,那样,因为黄色的那段S2和S1是相等的,那么在S1中找到的最长前缀后缀也和S2的后缀相等,这时,如果A点那里和q相等,那么next[q]就是棕那段长度+1喽~如果不相等,再向前减,对,这个过程就是代码里那里【k=next[k];】。如果到紫色的那里B和q相同,那么next[q]为紫色的长度+1.如果一直不相等,只能是0喽~
代码如下(代码原网址链接):

void makeNext(const char P[],int next[])
{
int q,k;//q:模版字符串下标;k:最大前后缀长度
int m = strlen(P);//模版字符串长度
next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0
for (q = 1,k = 0; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
{
while(k > 0 && P[q] != P[k])//递归的求出P[0]•••P[q]的最大的相同的前后缀长度k
k = next[k-1];
if (P[q] == P[k])//如果相等,那么最大相同前后缀长度加1
{
k++;
}
next[q] = k;
}
}

但很多时候next数组的意义是:next[i]表示第0个元素到第i-1个元素组成的字符串的前缀后缀,也就是如果把上面讨论的数组定义为nexta的话,那么nexta[i]=next[i+1] , 即nexta[0]=next[1]……nexta[n-1]=next[n],并定义next[0]=-1。
代码如下:

void GetNext()
{
//这个代码的原理和上差不多,就是改的短了些
int j = 0, k = -1;
Next[0] = -1;
while (j <= tlen)
{
if (k == -1 || T[j] == T[k])
{
Next[++j] = ++k;
}
else
k = Next[k];
}
} int KMP_Index()
{
int i = 0, j = 0;
GetNext();
while (i < slen && j < tlen)
{
if (j == -1 || S[i] == T[j])
{
i++;
j++;
}
else
j = Next[j];
}
if (j == tlen)
return i - tlen;
return -1;
}

  

也可以求一个字串出现的次数,代码稍作改动即可:

int KMP_Count()
{
int ans = 0;
int i = 0, j = 0;
GetNext();
while (i != slen && j != tlen)
{
if (S[i] == T[j] || j == -1)
++i, ++j; //第一次发现还可以这样写~
else
j = Next[j];
if (j == tlen)
{
++ans;
j = Next[j];
}
}
return ans;
}

  

举例说明理解一下

对于tytytyty

tytytyty                // ↓子串    // ↓前缀后缀
next[0] = -1
next[1] = 0 // t
next[2] = 0 // ty
next[3] = 1 // tyt // t
next[4] = 2 // tyty // ty
next[5] = 3 // tytyt // tyt
next[6] = 4 // tytyty // tyty
next[7] = 5 // tytytyt // tytyt
next[8] = 6 // tytytyty // tytyty

  

KMP入门题

hdu2087 AC代码:

/*******************************************************
Problem : 2087 ( 剪花布条 ) Judge Status : Accepted
RunId : 14705531 Language : G++ Author : G_lory
Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta
*******************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int N = 1005; char s[N]; // 原字符串
char t[N]; // 匹配子串
char nt[N]; // nt[i]表示t第0~i-1个元素组成的字符串的前缀后缀 int slen, tlen; // 字符串 s, t 的长度 void get_next()
{
int j = 0, k = -1;
nt[0] = -1;
while (j <= tlen)
{
if (k == -1 || t[j] == t[k])
{
nt[++j] = ++k;
}
else
k = nt[k];
}
} int kmp_cnt()
{
int ans = 0;
int i = 0, j = 0;
get_next();
while (i != slen && j != tlen)
{
if (s[i] == t[j] || j == -1)
++i, ++j;
else
j = nt[j];
if (j == tlen)
{
++ans;
//j = nt[j];
j = 0;
}
}
return ans;
} int main()
{
while (scanf("%s", s) != EOF) {
slen = strlen(s);
if (slen == 1 && s[0] == '#') break;
scanf("%s", t);
tlen = strlen(t);
printf("%d\n", kmp_cnt());
}
return 0;
}

  

hdu1711 AC代码:

/***********************************************************
Problem : 1711 ( Number Sequence ) Judge Status : Accepted
RunId : 14705762 Language : G++ Author : G_lory
Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta
************************************************************/
#include <iostream>
#include <cstdio>
using namespace std; int ss[1000005];
int tt[10005];
int nt[10005];
int slen, tlen; void get_next()
{
int j = 0, k = -1;
nt[0] = -1;
while (j <= tlen)
{
if (k == -1 || tt[j] == tt[k])
{
nt[++j] = ++k;
}
else
k = nt[k];
}
} int kmp_idx()
{
int i = 0, j = 0;
get_next();
while (i < slen && j < tlen)
{
if (j == -1 || ss[i] == tt[j]) ++i, ++j;
else j = nt[j];
}
if (j == tlen)
return i - tlen;
return -1;
} int main()
{
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &slen, &tlen);
for (int i = 0; i < slen; ++i) scanf("%d", ss + i);
for (int i = 0; i < tlen; ++i) scanf("%d", tt + i);
int ans = kmp_idx();
printf("%d\n", ans == -1 ? -1 : ans + 1);
}
return 0;
}

  

KMP学习总结的更多相关文章

  1. KMP学习之旅

    说起kmp就要从字符串的匹配说起,下面我们谈谈字符串的匹配 给定一个原字符串:bababababababababb,再给定一个模式串:bababb,求模式串是否在源字符串中出现 最简单的方法就是遍历源 ...

  2. KMP学习笔记

    功能 字符串T,长度为n. 模板串P,长度为m.在字符串T中找到匹配点i,使得从i开始T[i]=P[0], T[i+1]=P[1], . . . , T[i+m-1]=P[m-1] KMP算法先用O( ...

  3. KMP学习

    刚才看了(连接)写的翻译,把kmp算法的工作过程讲的很不错,kmp算法的核心是next,next为什么要那么赋值?其实就是前缀和后缀的最大匹配值,用这个值在匹配失败的时候可以跳过一个不必要的匹配.   ...

  4. kmp学习小结

    KMP 简要说明 \(kmp\)是一个非常神奇的东西.它的\(fail(next)\)数组\(f[i]\)就表示\(1\)~\(i\)这个串的最长公共前缀后缀长度.根据这个\(fail\)数组,在匹配 ...

  5. 扩展kmp学习笔记

    kmp没写过,扩展kmp没学过可还行. 两个愿望,一次满足 (该博客仅用于防止自己忘记,不保证初学者能看懂我在瞎bb什么qwq) 用途 对于串\(s1,s2\),可以求出\(s2\)与\(s1\)的每 ...

  6. 126B Password[扩展kmp学习]

    题目大意 给你一个字符串,求它的一个子串使得这个子串即使前缀又是后缀又出现在不是前缀且不是后缀的地方 分析 扩展kmp就是定义z[i]表示i~n的子串与整个串的最长公共前缀的长度是z[i] 所以这个题 ...

  7. 扩展kmp 学习笔记

    学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的-- 首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度 一个比较好的理解于实现方式是类似于 \(manac ...

  8. Kuangbin 带你飞 KMP扩展KMP Manacher

    首先是几份模版 KMP void kmp_pre(char x[],int m,int fail[]) { int i,j; j = fail[] = -; i = ; while (i < m ...

  9. poj(2406) kmp

    题目链接:https://vjudge.net/problem/POJ-2406 kmp学习:https://blog.csdn.net/starstar1992/article/details/54 ...

随机推荐

  1. vim emmet配置

    http://nerd-is.in/2013-12/learning-vim-again-1-install-vundle/ http://nerd-is.in/2013-12/learn-vim-a ...

  2. SDC(7) -- 关于使能信号的时序放松

    先看下图: 假如使能信号的有效时间为时钟周期的2倍,此时需要使用 set_multicycle_path 放松使能信号 sel_xy_nab ,若是每个寄存器使能端都约束一遍,那就太麻烦了: 这时可以 ...

  3. <一> MVC - HtmlHelper

    HtmlHelper类位于System.Web.Mvc.Html之中主要有七个静态类组成: FormExtensions - BeginForm, BeginRouteForm, EndForm In ...

  4. Mongodb使用总结

    学习Mongodb已经有半年多了,为啥学习它,工作需要啊.好了,废话不说,总结在实际项目应用中的几点问题. 学习总结 首先,mongodb基本上既照顾到了sql某些语法,又有nosql的许多优点.入门 ...

  5. 条件编译用法(#ifndef #define #endif#else)

    1. 文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都include了同一个头文件.而编译时,这两个C文件要一同编译成一个可运行文件,于是问题 ...

  6. 认识变量------JAVA

    声明变量: variables must have a type variables must have a name int count // type int //count name 变量就是杯 ...

  7. Spring 数据源配置二:多数据源

    通过上一节  Spring 数据源配置一: 单一数据源  我们了解单一数据源的配置, 这里我们继续多个数据源的配置 如下(applicationContent.xml 内容) 一:  Spring   ...

  8. Ubuntu 14.04数据库服务器--mysql的安装和配置

    mysql是Oracle公司的一种开放源代码的关系型数据库管理系统,被广泛应用于各中小网站,是一种跨平台的数据库管理系统,现在介绍一下如何在Ubuntu 14.04上安装和配置mysql 1. 更新源 ...

  9. [unity菜鸟] 修改发布成web后的logo

    1. 原始效果  (tip:在4.x的书中有介绍) 2. 打开.html文件原始代码如下 <script type='text/javascript' src='jquery.min.js'&g ...

  10. SPRING IN ACTION 第4版笔记-第四章Aspect-oriented Spring-001-什么是AOP

    一. Aspect就是把会在应用中的不同地方重复出现的非业务功能的模块化,比如日志.事务.安全.缓存 In software development, functions that span mult ...