算法总结篇---KMP算法
写在前面
仅为自用,不做推广
一起来看猫片吧!
一篇不错的博客,然而我闷了一下午还是不会,看了看书算是搞懂了
博客里面各种性质讲的非常详细,有空可以回看一下
核心的两段代码
nxt数组预处理:
我这里使用pre表示nxt数组,用go表示要匹配的串
void init(){//预处理pre数组
int len = strlen(go + 1);
int j = 0;
for(int i = 1; i < len; ++i){
while(j > 0 && go[i + 1] != go[j + 1]) j = pre[j];
if(go[i + 1] == go[j + 1]) ++j;
pre[i + 1] = j;
}
}
原字符串的匹配:
for(int i = 0; i < len1; ++i){
while(j > 0 && s[i + 1] != go[j + 1]) j = pre[j];
if(s[i + 1] == go[j + 1]) ++j;
// cout<<"i:"<<i<<" "<<j<<endl;
if(j == len2){//如果匹配完成
cnt++;
j = 0;
}
}
例题
剪花布条
直接KMP匹配即可,匹配成功将匹配串的指针置为0
Radio Transmission
一个结论题,答案为 \(n - nxt[n]\),好像与nxt数组本身的性质有关
OKR-Periods of Words
/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define orz cout<<"lkp AK IOI!"<<endl
using namespace std;
const int MAXN = 1e6+6;
const int INF = 1;
const int mod = 1;
int n;
LL ans = 0;
char s[MAXN];
int pre[MAXN];
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
}
void init(){
int j = 0;
for(int i = 1; i <= n; ++i){
while(j > 0 && s[i + 1] != s[j + 1]) j = pre[j];
if(s[i + 1] == s[j + 1]) ++j;
pre[i + 1] = j;
}
}
int main()
{
n = read();
cin >> (s + 1);
init();
for(int i = 1; i <= n; ++i){
int j = i;
while(pre[j]) j = pre[j];
if(pre[i]) pre[i] = j;
ans += (i - j);
}
printf("%lld", ans);
return 0;
}
似乎在梦中见过的样子
看这位大佬的题解
/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define orz cout<<"lkp AK IOI!"<<endl
using namespace std;
const int MAXN = 2e4+6;
const int INF = 1;
const int mod = 1;
int n, k, cnt = 0;
char s[MAXN];
int pre[MAXN];
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
}
void Kmp(int l){
int j = l - 1;
pre[l] = pre[l - 1] = j;
for(int i = l; i < n; ++i){
while(j > l - 1 && s[j + 1] != s[i + 1]) j = pre[j];
if(s[j + 1] == s[i + 1]) j++;
pre[i + 1] = j;
}
for(int i = l; i < n; ++i){
j = pre[i + 1];
while(j > l - 1 && l + 2 * (j - l + 1) > i + 1) j = pre[j];
if(j - l + 1 >= k) cnt++;
}
}
int main()
{
cin >> (s + 1);
k = read();
n = strlen(s + 1);
for(int i = 1; i <= n; ++i) Kmp(i);
printf("%d", cnt);
return 0;
}
Censoring
主要思路是开一个栈,来储存还未被消去的字符串
如果一个串匹配完成,从弹出相应的串
在入栈是顺便记录入栈字符的失陪位置,匹配完一个串后可以直接从栈顶所对字符的失陪位置开始匹配
从前到后跑一遍即可,复杂度 \(O(n)\)
/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define orz cout<<"lkp AK IOI!"<<endl
using namespace std;
const int MAXN = 1e6+6;
const int INF = 1;
const int mod = 1;
char s[MAXN], t[MAXN];
int lens, lent;
int pre[MAXN], f[MAXN];
int stc[MAXN], sc = 0;
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
}
void init(){
int j = 0;
for(int i = 1; i <= lent; ++i){
while(j && t[i + 1] != t[j + 1]) j = pre[j];
if(t[i + 1] == t[j + 1]) ++j;
pre[i + 1] = j;
}
}
int main()
{
cin >> (s + 1);
cin >> (t + 1);
lens = strlen(s + 1);
lent = strlen(t + 1);
init();
for(int i = 0, j = 0; i < lens; ++i){
while(j && s[i + 1] != t[j + 1]) j = pre[j];
if(s[i + 1] == t[j + 1]) ++j;
f[i + 1] = j;
stc[++sc] = i + 1;
if(j == lent){
sc -= lent, j = f[stc[sc]];
}
}
for(int i = 1; i <= sc; i++){
printf("%c", s[stc[i]]);
}
return 0;
}
算法总结篇---KMP算法的更多相关文章
- LeetCode刷题--基础知识篇--KMP算法
KMP算法 关于字符串匹配的算法,最知名的莫过于KMP算法了,尽管我们日常搬砖几乎不可能去亲手实现一个KMP算法,但作为一种算法学习的锻炼也是很好的,所以记录一下. KMP算法是根据三位作者(D.E. ...
- 算法起步之kmp算法
[作者Idlear 博客:http://blog.csdn.net/idlear/article/details/19555905] 这估计是算法连载文章的最后几篇了,马上就要 ...
- 算法笔记之KMP算法
本文是<算法笔记>KMP算法章节的阅读笔记,文中主要内容来源于<算法笔记>.本文主要介绍了next数组.KMP算法及其应用以及对KMP算法的优化. KMP算法主要用于解决字符串 ...
- 问题 1690: 算法4-7:KMP算法中的模式串移动数组
题目链接:https://www.dotcpp.com/oj/problem1690.html 题目描述 字符串的子串定位称为模式匹配,模式匹配可以有多种方法.简单的算法可以使用两重嵌套循环,时间复杂 ...
- 字符串匹配(BF算法和KMP算法及改进KMP算法)
#include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...
- 一篇别人写的Kmp算法的讲解,多看多得
kmp算法的理解与实现 博客分类: algorithms 算法 KMP算法曾被我戏称为看毛片算法,当时笑喷......大三那个时候硬着头皮把算法导论的kmp算法啃完,弄懂了kmp算法 的原理 ...
- KMP算法,看这篇就够了!
普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...
- Java数据结构之字符串模式匹配算法---KMP算法
本文主要的思路都是参考http://kb.cnblogs.com/page/176818/ 如有冒犯请告知,多谢. 一.KMP算法 KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,其基 ...
- 浅谈Manacher算法与扩展KMP之间的联系
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
随机推荐
- tomcat能正常启动,但是http://localhost:8080/网页就是打不开,报404
问题描述: 在IDE中创建了一个新的Servers,并且加入一个Tomcat.然后启动服务,进入浏览器,输入localhost:8080进入,显示错误.服务是可以正常启动的,而且没有任何异常. 问题描 ...
- Mysql 8.0 相关命令
1.dos窗口命令登陆. 管理员/普通用户登陆(账号/密码:root/rootpwd) mysql -hlocalhost -uroot -prootpwd 普通用户登陆(root管理员的不可以使用这 ...
- 零基础学习qt4 第七章的第一个例子
#include <QtGui> #include "extensionDlg.h" ExtensionDlg::ExtensionDlg(QWidget *paren ...
- Redis的内存淘汰
Redis占用内存大小 我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限,所以我们在使用Redis的时候可以配置Redis能使用的最大的内存大小. 1.通过配置文件配置 ...
- 第13章节 BJROBOT 雷达跟随【ROS全开源阿克曼转向智能网联无人驾驶车】
雷达跟随说明:注意深度摄像头的 USB 延长线,可能会对雷达扫描造成影响, 所以在雷达跟随前,把深度摄像头的 USB 延长线取下.另外雷达跟随范围大概是前方 50cm 和 120°内扫描到的物体都可以 ...
- G客短信平台开发,资源短信功能使用说明
短信平台使用资源短信操作顺序 联系微信:290615413 1:登录客户端 2:点击左侧 发送短信中的,资源短信 3:资源短信申请操作 3.1:选择相应的省市 会显示资源数量. 3.2:然后输入申请 ...
- Spark学习进度-实战测试
spark-shell 交互式编程 题目:该数据集包含了某大学计算机系的成绩,数据格式如下所示: Tom,DataBase,80 Tom,Algorithm,50 Tom,DataStructure ...
- 解决surfacebook无法运行64位虚拟机的问题
如果您嫌烦请直接看英文部分解决方案,另外windows专业版内置的hyper-v也是一款及其好用的虚拟机. 网上各种方案都尝试过,但是每次使用VMware创建64为虚拟机的时候总会显示不支持64位虚拟 ...
- Cisco常用命令
• 首次配置网络设备 ○ 需要使用Console线连接进行初始化配置 § 在PC使用"超级终端"或其他软件. • 交换机的工作模式: ...
- 集成spring框架的web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" ...