kmp理解
来源:互联网 发布:淘宝支点运动是真的吗 编辑:程序博客网 时间:2024/05/01 18:33
kmp算法的核心就是对next 数组的理解和构造,,以前一直都理解错了于是一直背kmp代码模版[其实也是很好背的orz,,今天终于纠正过来。
首先对next[i]下一个定义。
如果子串第i位与母串第j位配失败了,则子串的第next[i]位 应该与母串第j位重新匹配。即,next[i]是子串与母串j重新匹配的位点。
而这个位点有什么特性呢?子串[0~next[i]-1]与子串[i-next[i]~i-1]是完全相同的。而这个相同的串,对于第i-1位来说是最长的。
因此,子串的[0~next[i]-1]位 与母串的[j-next[i]~j-1]是相同的。只需要从next[i]起继续与母串的第j位进行比较即可。不需要再从头开始比较,这样就节省了时间。
其次是next数组的构造问题。
它其实有一个继承的思想在里面,也就是我们说的递推。
对于sz[i] 我们想要找到 它的next[i], 可以直接继承next[i-1]里信息。举个栗子:比如此时的next[i-1]=5 意味着i-1已经和前 4 个字符相匹配了,它的前一位的最长前缀为4。
而这个时候我们想知道next[i]为多少,我们需要知道以sz[i -1]结尾的最长前缀为多少,因此我们就需要比较sz[next[i-1]]与sz[i-1]是否相同,如果相同则说明,以sz[i-1]结尾的最长前缀为5 所以next[i]==5+1(next[i-1]+1);
但如果不相同呢?这就相当于子串与母串匹配失败了一样,我们需要向前移动 找到一个最近的位点与sz[i-1]重新匹配,而这个位点正是存在next[next[i-1]]里的。于是就可以乳齿不断的往前递推。直到找到与sz[i-1]相等的那个位点next[p],或者找到了子串的起始点。
最后就可以得到以sz[i-1]为末位的最长前缀 而 next[i]=next[p]+1;
总而言之,之所以觉得绕是因为,next[i]始终表示的是 以sz[i-1]为末位的最长前缀的长度的下一位。。。。。
又一次觉得复杂度是一个谜。。。不要问窝为什么是O(m+n)
写的小作文,估计只有窝自己能看懂吧qwq。。。
下面是一道裸kmp。。。。但是在VJ上T了,HDU上A了。。。。。一定是窝写的太丑。。。。
HDU 1711:http://acm.hdu.edu.cn/showproblem.php?pid=1711
// Created by ZYD in 2015.// Copyright (c) 2015 ZYD. All rights reserved.//#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>#include <cstring>#include <climits>#include <string>#include <vector>#include <cmath>#include <stack>#include <queue>#include <set>#include <map>using namespace std;#define Size 100000#define ll long long#define mk make_pair#define pb push_back#define mem(array) memset(array,0,sizeof(array))typedef pair<int,int> P;int n,m,t,sm[1000005],sz[10005],nxt[10005];int kmp(){ int p=0; nxt[1]=0;nxt[2]=1; for(int i=3;i<=m;i++) { p=i-1; while(p>1 && sz[nxt[p]]!=sz[i-1]) p=nxt[p]; nxt[i]=nxt[p]+1; } int p1=1;int p2=1; while(p1<=n && p2<=m) { if(sm[p1]==sz[p2]) { p1++; p2++; continue; } p2=nxt[p2]; if(p2<1) { p1++; p2=1; } } if(p2>m) cout<<p1-p2+1<<endl; else cout<<-1<<endl; return 0;}int main(){ freopen("in.txt","r",stdin); cin>>t; while(t--) { cin>>n>>m; mem(sm);mem(sz);mem(nxt); for(int i=1;i<=n;i++) cin>>sm[i]; for(int i=1;i<=m;i++) cin>>sz[i]; kmp(); } return 0;}
- kmp理解
- kmp理解
- 理解KMP
- KMP理解
- 理解KMP
- KMP算法理解
- 深入理解KMP算法
- KMP算法的理解
- KMP的理解
- 理解KMP算法
- KMP新理解
- KMP算法初步理解
- 我理解之KMP
- 从头到尾理解KMP算法
- 从头到尾理解KMP算法
- KMP算法的理解
- KMP算法理解
- KMP算法---理解
- Triangle
- 命中缺高人指点
- 大型网站核心的架构(6-2)高性能
- [2013]蟠桃记
- NSDate
- kmp理解
- Java笔试和面试题目
- 设计模式之观察者
- 转 编程: VC++学习方法及书籍
- 写个益智小游戏 看你能过关不?
- NSNotificationCenter
- 逗号运算符
- Centos6.7 Centos7.0 安装OpenVSwitch痛苦经历
- SpringMVC文件的上传与下载