写在前面

仅为自用,不做推广

一起来看猫片吧!

一篇不错的博客,然而我闷了一下午还是不会,看了看书算是搞懂了

博客里面各种性质讲的非常详细,有空可以回看一下

核心的两段代码

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算法的更多相关文章

  1. LeetCode刷题--基础知识篇--KMP算法

    KMP算法 关于字符串匹配的算法,最知名的莫过于KMP算法了,尽管我们日常搬砖几乎不可能去亲手实现一个KMP算法,但作为一种算法学习的锻炼也是很好的,所以记录一下. KMP算法是根据三位作者(D.E. ...

  2. 算法起步之kmp算法

    [作者Idlear  博客:http://blog.csdn.net/idlear/article/details/19555905]            这估计是算法连载文章的最后几篇了,马上就要 ...

  3. 算法笔记之KMP算法

    本文是<算法笔记>KMP算法章节的阅读笔记,文中主要内容来源于<算法笔记>.本文主要介绍了next数组.KMP算法及其应用以及对KMP算法的优化. KMP算法主要用于解决字符串 ...

  4. 问题 1690: 算法4-7:KMP算法中的模式串移动数组

    题目链接:https://www.dotcpp.com/oj/problem1690.html 题目描述 字符串的子串定位称为模式匹配,模式匹配可以有多种方法.简单的算法可以使用两重嵌套循环,时间复杂 ...

  5. 字符串匹配(BF算法和KMP算法及改进KMP算法)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #include<cstring> ...

  6. 一篇别人写的Kmp算法的讲解,多看多得

    kmp算法的理解与实现 博客分类: algorithms 算法      KMP算法曾被我戏称为看毛片算法,当时笑喷......大三那个时候硬着头皮把算法导论的kmp算法啃完,弄懂了kmp算法 的原理 ...

  7. KMP算法,看这篇就够了!

    普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...

  8. Java数据结构之字符串模式匹配算法---KMP算法

    本文主要的思路都是参考http://kb.cnblogs.com/page/176818/ 如有冒犯请告知,多谢. 一.KMP算法 KMP算法可以在O(n+m)的时间数量级上完成串的模式匹配操作,其基 ...

  9. 浅谈Manacher算法与扩展KMP之间的联系

    首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一   ...

随机推荐

  1. IDEA使用SVN上传项目

    文章最后附上svn服务器和客户端下载地址 一.IDEA集成SVN 二.查看SVN仓库 调出svn视图: 连接svn服务器: 连接后效果如下: 忽略上传文件 忽略文件如下:可以选择按规则匹配 .idea ...

  2. JTable写入数据库内容

    /*JTable中导入数据库数据. 创建2个Vector col和dat col存入字段名 dat存入数据内容. dbname=new JTable(dat,col); */package demo; ...

  3. .NET 云原生架构师训练营(模块二 基础巩固 MongoDB 聚合)--学习笔记

    2.5.5 MongoDB -- 聚合 排序 索引类型 创建索引 排序 // 升序 db.getCollection('author').find({}).sort({"age": ...

  4. 将WCF迁移到gRPC

    使用protobuf-net.Grpc将WCF服务迁移到gRPC非常简单.在这篇博文中,我们将看看它到底有多简单.微软关于将WCF服务迁移到gRPC的官方指南只提到了Gooogle.Protobuf方 ...

  5. Linux LVM Logical Volume Management 逻辑卷的管理

    博主是一个数据库DBA,但是一般来说,是不做linux服务器LVM 逻辑卷的创建.扩容和减容操作的,基本上有系统管理员操作,一是各司其职,专业的事专业的人做,二是做多了你的责任也多了,哈哈! 但是li ...

  6. Face_to_object_design

    二.实例 掷骰子游戏:三粒骰子,掷两次,比较两次的结果. 1.提炼 提炼对象:三粒骰子.游戏 提炼对象的属性和功能:掷骰子.比较点数 骰子: 属性:点数 功能:随机获取一个1~6之间的整数值. 游戏: ...

  7. CSS 奇技淫巧:动态高度过渡动画

    这个问题源自于掘金上的一个留言,一个朋友问到,为什么我下面这段代码的高度过渡动画失效了? 伪代码大概是这样: { height: unset; transition: all 0.3s linear; ...

  8. 路由器开启远程控制(ssh或telent)

    • 远程控制        ○ 开启远程控制            § conf t             § line vty 0 4                □ 0 4 意思是最多允许5个 ...

  9. Eplan P8 2.7 加密狗 感叹号 解决方法

    Eplan安装完加密狗后一直感叹号异常,最近也是查了很多办法,最后发现是少了个驱动的原因. 就是上面这个驱动,这里放上驱动链接:https://lanzous.com/id5gi8f ,或者随便找一个 ...

  10. 计算机考研复试真题 abc

    题目描述 设a.b.c均是0到9之间的数字,abc.bcc是两个三位数,且有:abc+bcc=532.求满足条件的所有a.b.c的值. 输入描述: 题目没有任何输入. 输出描述: 请输出所有满足题目条 ...