KMP入门
First.先上一份最原始的无任何优化的代码(暴力):
#include <iostream>
#include <cstring>
using namespace std;
char s[1000],p[1000]; inline int getans(char* s,char* p){
int sl=strlen(s),pl=strlen(p);
int i=0,j=0;
while(i<sl && j<pl){
if(s[i]==p[j])
i++,j++;
else{
i=i-j+1;
j=0;
}
}
if(j==pl) return i-j;
else return -1;
} int main(){
cin>>s>>p;
int ans=getans(s,p);
cout<<ans<<endl;
return 0;
}
对于文本串S和模拟串P,进行匹配。
i表示S串的位置,同理,j表示P串的位置;
若当前字符匹配,则进行下一个(i++,j++);
否则,将P归零,S回溯到上一次匹配的位置;
输出的是第一次匹配的位置。
Second.开始第一次优化(KMP):
在上述的暴力中,我们可以发现,每次失配时,i返回到了前面很远的地方,所以我们想搞这样一个东西;
它具备一个特殊性质:
在每次失配是,直接让P跳到这个位子上,大大减少复杂度。
在此,我们需要引入一个叫做next的数组;
但是,仍然有最坏的情况,就是需要重新匹配;
那么此时的next[i]=0或-1,表示重头在来;
若next[i]=k,则表示P跳过了k个字符。
简略代码:
inline int KMPsearch(char* s,char* p){
int sl=strlen(s),pl=strlen(p);
int i=0,j=0;
while(i<sl && j<pl){
if(s[i]==p[j]||j==-1)//j==-1表示匹配成功,进行后续的字符匹配
i++,j++;
else
j=nxt[j];//i不用变,j直接跳到预处理好的next[j]处
}
if(j==pl) return i-j;
else return -1;
}
1.
next数组记录的是长度最大且相等的前缀后缀;
举个例子:
P1: ABA
P2: ABAB
在P1中,他有长度为1的相同前缀后缀A
在P2中,他有长度为2的相同前缀后缀AB
(盗图勿喷)
2.
我们来求next数组;
将第一步中的长度稍作变形即可;
(同上)
整体右移一位,将第一位赋值为-1。
也可以这样理解:(与-1无关了就)
如果相等,则该位的next值就是前一位的next值加上1;
如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。
3.
代码求next数组;
inline void GetNext2(char *p,int nxt[]){
int pl=strlen(p);
nxt[0]=-1;
int k=-1;
int j=0;
while(j<pl-1){
if(k==-1 || p[j]==p[k]){
++j,++k;
if(p[j]!=p[k])
nxt[j]=k;
else nxt[j]=nxt[k];
}
else k=nxt[k];
}
}
Third.对于next数组的优化:
在上文所述中,有个小问题:
就是说,在j向后跳到了next[k]时,必然失配,
就是因为p[j]=p[next[j]];
那就要处理出所有这种情况,递归
next[j]=p[next[next[j]]]。
Finally.整体代码(可直接食用哦):
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; char s[100],p[100];
int nxt[100]; inline void GetNext2(char *p,int nxt[]){
int pl=strlen(p);
nxt[0]=-1;
int k=-1;
int j=0;
while(j<pl-1){
if(k==-1 || p[j]==p[k]){
++j,++k;
if(p[j]!=p[k])
nxt[j]=k;
else nxt[j]=nxt[k];
}
else k=nxt[k];
}
} inline int KMPsearch(char* s,char* p){
int sl=strlen(s),pl=strlen(p);
int i=0,j=0;
while(i<sl && j<pl){
if(s[i]==p[j]||j==-1)
i++,j++;
else
j=nxt[j];
}
if(j==pl) return i-j;
else return -1;
} int main(){
cin>>s>>p;
GetNext2(p,nxt);
int ans=KMPsearch(s,p);
cout<<ans<<'\n';
return 0;
}
嗯,真香
KMP入门的更多相关文章
- zstu.4194: 字符串匹配(kmp入门题&& 心得)
4194: 字符串匹配 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 206 Solved: 78 Description 给你两个字符串A,B,请 ...
- 题解报告:hdu 2087 剪花布条(KMP入门)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面 ...
- hdu 1358 Period(KMP入门题)
Period Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
- KMP入门题目[不定期更新]
HDU 1711 Number Sequence(模板题) #include <cstdio> ; ; int N, M; int textS[MAXN]; int tarS[MAXL]; ...
- KMP入门(匹配)
Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M ...
- hdu 1358 period KMP入门
Period 题意:一个长为N (2 <= N <= 1 000 000) 的字符串,问前缀串长度为k(k > 1)是否是一个周期串,即k = A...A;若是则按k从小到大的顺序输 ...
- hdu 1686 & poj 2406 & poj 2752 (KMP入门三弹连发)
首先第一题 戳我穿越;http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目大意好理解,每组输入一个子串和一个母串,问在母串中有多少个子串? 文明人不要暴力 ...
- HDU2203(KMP入门题)
亲和串 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- HDU2087(KMP入门题)
剪花布条 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HUD1686(KMP入门题)
Oulipo Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
随机推荐
- 解Bug之路-记一次存储故障的排查过程
解Bug之路-记一次存储故障的排查过程 高可用真是一丝细节都不得马虎.平时跑的好好的系统,在相应硬件出现故障时就会引发出潜在的Bug.偏偏这些故障在应用层的表现稀奇古怪,很难让人联想到是硬件出了问题, ...
- 使用请求头认证来测试需要授权的 API 接口
使用请求头认证来测试需要授权的 API 接口 Intro 有一些需要认证授权的接口在写测试用例的时候一般会先获取一个 token,然后再去调用接口,其实这样做的话很不灵活,一方面是存在着一定的安全性问 ...
- html中隐藏域hidden
基本语法: <input type="hidden" name="field_name" value="value"> 作用: ...
- Docker+Selenium+TestNG+Maven+Jenkins环境搭建
一.Selenium环境准备 standalone-chrome Docker容器启动: docker pull selenium/standalone-chrome version: '3' ser ...
- is ==小数据池编码解码
== 比较 比较的是两边的值 is 比较 比较的是内存地址 判断两个东西指向的是不是同一个对象 取内存地址 id() 小数据池 ...
- CGAL 获取相关功能的依赖头文件
CGAL 获取相关功能的依赖头文件 由于CGAL是header include only.只需要头文件就可以实现相关的功能.有时候为了实现一个简单的功能, 在研究具体实现的时候能够知道这个功能对应的头 ...
- 利用ssm框架做一个客户管理系统
1. 需求分析 (1)初始化查询条件下拉列表 (2)展示客户列表,并且可以根据查询条件过滤查询结果,并且实现分页处理. (3)修改客户信息: 1)点击客户列表中的“修改”按钮弹出客户信息修改对话框,并 ...
- 布局之: flex(CSS3新增)
flex 基本概念 flex布局(flex是flexible box的缩写), 也称为弹性盒模型 .将属性和属性值(display:flex; )写在哪个标签样式中,谁就是 容器:它的所有子元素自动成 ...
- DP:0-1背包问题
[问题描述] 0-1背包问题:有 N 个物品,物品 i 的重量为整数 wi >=0,价值为整数 vi >=0,背包所能承受的最大重量为整数 C.如果限定每种物品只能选择0个或1个,求可装的 ...
- 三角函数与缓入缓出动画及C#实现(图文讲解)
日常经常能看到缓入缓出的动画效果,如: 1,带缓入缓出效果的滚动条: 2,带缓入缓出效果的呼吸灯: 像上面这种效果,就是用到了三角函数相关的知识,下面将从头开始一步步去讲解如何实现这种效果. 一.基础 ...