KMP学习总结
初学,理解可能不是那么准确~~
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学习总结的更多相关文章
- KMP学习之旅
说起kmp就要从字符串的匹配说起,下面我们谈谈字符串的匹配 给定一个原字符串:bababababababababb,再给定一个模式串:bababb,求模式串是否在源字符串中出现 最简单的方法就是遍历源 ...
- 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( ...
- KMP学习
刚才看了(连接)写的翻译,把kmp算法的工作过程讲的很不错,kmp算法的核心是next,next为什么要那么赋值?其实就是前缀和后缀的最大匹配值,用这个值在匹配失败的时候可以跳过一个不必要的匹配. ...
- kmp学习小结
KMP 简要说明 \(kmp\)是一个非常神奇的东西.它的\(fail(next)\)数组\(f[i]\)就表示\(1\)~\(i\)这个串的最长公共前缀后缀长度.根据这个\(fail\)数组,在匹配 ...
- 扩展kmp学习笔记
kmp没写过,扩展kmp没学过可还行. 两个愿望,一次满足 (该博客仅用于防止自己忘记,不保证初学者能看懂我在瞎bb什么qwq) 用途 对于串\(s1,s2\),可以求出\(s2\)与\(s1\)的每 ...
- 126B Password[扩展kmp学习]
题目大意 给你一个字符串,求它的一个子串使得这个子串即使前缀又是后缀又出现在不是前缀且不是后缀的地方 分析 扩展kmp就是定义z[i]表示i~n的子串与整个串的最长公共前缀的长度是z[i] 所以这个题 ...
- 扩展kmp 学习笔记
学习了一下这个较为冷门的知识,由于从日报开始看起,还是比较绕的-- 首先定义 \(Z\) 函数表示后缀 \(i\) 与整个串的 \(lcp\) 长度 一个比较好的理解于实现方式是类似于 \(manac ...
- Kuangbin 带你飞 KMP扩展KMP Manacher
首先是几份模版 KMP void kmp_pre(char x[],int m,int fail[]) { int i,j; j = fail[] = -; i = ; while (i < m ...
- poj(2406) kmp
题目链接:https://vjudge.net/problem/POJ-2406 kmp学习:https://blog.csdn.net/starstar1992/article/details/54 ...
随机推荐
- 关于Qt5 UI设计的一些小知识
(1) 获取textEdit中的值 QString str = ui->textedit->toPlainText(); // 这是普通文本 p=str.toInt(); ...
- windows azure tools for mac
http://azure.microsoft.com/en-us/documentation/articles/xplat-cli/?fb=zh-cn http://www.windowsazure. ...
- VSCode调试go
VSCode调试go语言出现:exec: "gcc": executable file not found in %PATH% 1.问题描述 由于安装VS15 Preview ...
- 用PYTHON硬写SOCKET
这个文章的系列很有意思,练练~~: http://python.jobbole.com/82763/ :) 第一步,最简单的SERVER和CLIENT.感觉和写JAVA,C的最简单的一样一样的,,看来 ...
- [模拟]Codeforces509C Sums of Digits
题目链接 题意:给n个数a[i], 要求b[i]每位数的和等于a[i], 并且b[i]要严格递增 求最小的b[i] b[0]最小一定是X9999...这样的形式 后面的b[i]位数一定大于等于前一个 ...
- JS 中Promise 模式
异步模式在web编程中变得越来越重要,对于web主流语言Javscript来说,这种模式实现起来不是很利索,为此,许多Javascript库(比如 jQuery和Dojo)添加了一种称为promise ...
- 【POJ】2823 Sliding Window
单调队列. /* 2823 */ #include <iostream> #include <sstream> #include <string> #include ...
- 【HDOJ】1069 Monkey and Banana
DP问题,我是按照边排序的,排序既要考虑x也要考虑y,同时在每个面中,长宽也要有序.还有注意状态转移,当前高度并不是之前的最大block叠加的高度,而是可叠加最大高度+当前block高度或者是当前bl ...
- BOM List demo
select level level_id, t.* from (select msi1.segment1 farther_item, msi1.inv ...
- bzoj1965
很明显,求方程x*2^m=L (mod n+1)的解(1<=x<=n) var n,m,l,x,y,p:int64; function quick(x:int64):int64; var ...