KMP(模板)
算法讲解: KMP算法最浅显易懂
模板来源: 从头到尾彻底理解KMP
首先:KMP的模板为:
void get_next(char *a, int *nex) {
nex[] = ;
for (int i = , j = ; i <= len; i++) {
while (j > && a[i] != a[j + ])j = nex[j];
if (a[i] == a[j + ])j++;
nex[i] = j;
}
return;
} int KMP(char *a, char *b) {//b为母串
for (int i = , j = ; i <= strlen(b + ); i++) {
while (j > && (j == strlen(a + ) || b[i] != a[j + ]))j = nex[j];
if (b[i] == a[j + ])j++;
f[i] = j;
//若a在b中出现,,返回出现的位置
//if(f[i]==strlen(a+1)){return i-strlen(a);}
}
return ;
}
例题:2018 UESTC Training for Search Algorithm & String——L主楼
题意:求字符串中的最短循环节,并输出该循环节
KMP最小循环节、循环周期:
定理:假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。
(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。
(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。
注意这里的len是原字符串的len+1;
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
int T, len;
char s[ + ];
int nex[ + ]; void get_next(char* p, int next[]){
int pLen = strlen(p) + ;//要求循环节长度时这里才+1
next[] = -;
int k = -;
int j = ;
while (j < pLen - ){
if (k == - || p[j] == p[k]){
++j;++k;
if (p[j] != p[k])
next[j] = k;
else
next[j] = next[k];
}
else{
k = next[k];
}
}
} int kmp(char* s, char* p){
int i = ;
int j = ;
int sLen = strlen(s);
int pLen = strlen(p);
while (i < sLen && j < pLen){
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == - || s[i] == p[j]){
i++;
j++;
}
else{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = nex[j];
}
}
if (j == pLen)
return i - j;
else
return -;
} int main() {
scanf("%d", &T);
while (T--) {
memset(nex, , sizeof(nex));
scanf("%d", &len);
scanf("%s", s);
len = strlen(s);
get_next(s, nex);
printf("%d\n", len - nex[len]);
for (int i = ; i < len - nex[len]; i++)
printf("%c", s[i]);
printf("\n");
}
return ;
}
HDU1711(数字KMP)
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
int T, len;
int len1, len2;
int s1[ + ];
int s2[ + ];
int nex[ + ]; void get_next(int* p, int next[]) {
int pLen = len2;//要求循环节长度时这里才+1
next[] = -;
int k = -;
int j = ;
while (j < pLen - ) {
if (k == - || p[j] == p[k]) {
++j; ++k;
if (p[j] != p[k])
next[j] = k;
else
next[j] = next[k];
}
else {
k = next[k];
}
}
} int kmp(int* s, int* p) {
int i = ;
int j = ;
int sLen = len1;
int pLen = len2;
get_next(s2, nex);
while (i < sLen && j < pLen) {
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == - || s[i] == p[j]) {
i++;
j++;
}
else {
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = nex[j];
}
}
if (j == pLen)
return i - j;
else
return -;
} int main() {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &len1, &len2);
for (int i = ; i < len1; i++)
scanf("%d", &s1[i]);
for (int i = ; i < len2; i++)
scanf("%d", &s2[i]);
if (kmp(s1,s2) == -)
printf("-1\n");
else
printf("%d\n", kmp(s1,s2)+);
}
return ;
}
KMP(模板)的更多相关文章
- hdu 1686 KMP模板
// hdu 1686 KMP模板 // 没啥好说的,KMP裸题,这里是MP模板 #include <cstdio> #include <iostream> #include ...
- Oulipo HDU 1686 KMP模板
题目大意:求模式串在主串中的出现次数. 题目思路:KMP模板题 #include<iostream> #include<algorithm> #include<cstri ...
- KMP模板(bin)
KMP模板 主要是kuangbin的模板,之后加了一点我的习惯和理解. kmpN() 作用:构造next数组 参数:模式串,模式串长度 kmpC() 作用:返回模式串在主串中出现的次数(可重复) 参数 ...
- HDU 1711 - Number Sequence - [KMP模板题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 1711 Number Sequence(KMP模板)
http://acm.hdu.edu.cn/showproblem.php?pid=1711 这道题就是一个KMP模板. #include<iostream> #include<cs ...
- 剪花布条---hdu2087(kmp模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 kmp模板题: #include <cstdio> #include <cst ...
- Oulipo----poj3461(kmp模板)
题目链接:http://poj.org/problem?id=3461 和 减花布条 的题对比一下: 求s2中s1的个数kmp模板: #include<stdio.h> #include& ...
- kmp模板 && 扩展kmp模板
kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...
- kuangbin专题16B(kmp模板)
题目链接: https://vjudge.net/contest/70325#problem/B 题意: 输出模式串在主串中出现的次数 思路: kmp模板 在 kmp 函数中匹配成功计数加一, 再令 ...
- [HDU1711]KMP模板
解题关键:1.直接套kmp模板即可,注意最后输出的位置,需要在索引的位置+1. 2.next用作数组名在oj中会编译错误, 3.选用g++,只有g++才会接受bits/stdc++.h OJ中g++和 ...
随机推荐
- 一个sio.c的实现及遇到的多任务执行问题
https://sourceforge.net/p/cadcdev/lwip/ci/491e00038f26dc5d775f120aa49519a066819ebf/tree/kos/sio.c /* ...
- Effective Java, Third Edition
https://github.com/jbloch/effective-java-3e-source-code 网址是 Effetive java的源码 effective-java-3e-sourc ...
- H5异步加载多图
异步加载多图(可能没啥用,加载慢)(图片预加载,提前给浏览器缓存图片) 1. 用一个计数变量记录需要加载的图片个数 2. 用new Image()去加载,加载完给此对象的src赋值要加载的url路径( ...
- SHELL下打包文件
SHELL下打包文件 在我们拿下webshell的时候,想要获取数据或者源码往往会用菜刀或者蚁剑去打包,但是这个时候往往就会出现很多问题,列如打包失败,或者是打包得不完整等等. 这个时候如果对方是wi ...
- 学习shiro最佳实践,绝对正确
按照https://blog.csdn.net/qq_34021712/column/info/26947学习,基本能解决shiro一切问题,谢谢该博主
- CCS过渡和动画
过渡 过渡能让使用过渡的元素在样式发生变化时(例如鼠标划过,单击按钮,点击图片时,颜色,尺寸,位置等样式发生变化),定义变化过程中的动画,让变化不再是瞬间产生. 过渡样式使用transition定义, ...
- [LeetCode] [链表] 相关题目总结
刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 ...
- css中的盒子模型是什么?
什么是CSS 盒子模型(Box Model) 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封装周 ...
- 升级了NinjaLoveFish Excel量化表格
为了方便查看均价和止盈值,新建了两列 这样做的好处就是,针对一个股票,可以实现不同的多个网格布局,然后分别实现各自的盈利设定. 例如这是网格1 那么同时也可以存在网格2 就可以实现多个网格布局到一个股 ...
- 最短路问题 Dijkstra算法- 路径还原
// 路径还原 // 求最短路,并输出最短路径 // 在单源最短路问题中我们很容易想到,既然有许多条最短路径,那将之都存储下来即可 // 但再想一下,我们是否要把所有的最短路径都求出来呢? // 实际 ...