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++和 ...
随机推荐
- 授权认证(IdentityServer4)
区别 OpenId: Authentication :认证 Oauth: Aurhorize :授权 输入账号密码,QQ确认输入了正确的账号密码可以登录 --->认证 下面需要勾选的复选框(获取 ...
- C#设计模式学习笔记:(9)组合模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7743118.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第四个模式--组 ...
- You (oracle) are not allowed to use this program (crontab)
检查一台ORACLE数据库服务器的crontab作业(用户为oracle,实际环境中可能为oracle.也有可能是其它用户)时,发现出现下面提示信息: $ crontab -l You (orac ...
- SpringBoot安全管理--(一)SpringSecurity基本配置
简介: Spring Boot针对Spring Security提供了自动化配置方案,因此可以使Spring Security非常容易地整合进Spring Boot项目中,这也是在Spring Boo ...
- 将short类型转换为char类型
void short2char(uint8_t *arr1, uint16_t *arr2, int len) { ; ; for (x; x < len; x++) { arr1[x++] = ...
- GHM论文笔记(CVPR2019)
目录 作者要解决的问题 Focal loss(CVPR2017) Focal loss的解决方案 Focal loss的不足 设计思路 梯度与样本的关系 梯度分布计算方法:将0-1的梯度切bin,计算 ...
- kettle文本文件写入数据库,简单进行数据清洗
使用kettle7.0,java8.0,Navicat,实验数据使用全国肺炎2月24日的数据 1.建立关系 2.创建连接 如果是第一次连接,可能会出现连接不上的情况,这时候可能情况是没有将Mysql的 ...
- Electron – 基础学习(2): 项目打包成exe桌面应用 之electron-packager
项目创建完成,启动正常,接下来就是项目打包了.将测试Demo打包成exe桌面应用,点击exe文件,运行项目. 书接上文,创建项目有三种方式 Git拷贝.直接创建:通过electron社群提供的命令行工 ...
- (办公)记事本_Linux查找命令
参考谷粒学院的linux视频教程:http://www.gulixueyuan.com/course/300/task/7091/show 搜索命令 .whereis命令: 1.1.Linux whe ...
- 【python基础语法】数据类型:数值、字符串 (第2天课堂笔记)
""" 数据类型: 一.数值类型:整数 浮点数 布尔值 二.序列类型:字符串.列表 元祖 三.散列类型:字典 集合 可变数据类型: 列表 字典 集合,可以改动内存地址数据 ...