算法总结篇---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,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
随机推荐
- 史上最全java里面的锁
什么是锁 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制.锁旨在强制实施互斥排他.并发控制策略. 锁通常需要硬件支持才能有效实施.这 ...
- Java 为每个原始类型提供了哪些包装类型:
java的包装类型: 原始类型: boolean,char,byte,short,int,long,float,double 包装类型:Boolean,Character,Byte,Short,Int ...
- 如何实现Application event,观察者模式
spring 事件为bean 与 bean之间传递消息.一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件. spring事件使用步骤如下: 1.先 ...
- nohup命令说明-转载
转自:https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/ 我们知道,当用户注销(logout)或者网络断开时,终端会收到 HUP(hangu ...
- Java常用类学习笔记总结
Java常用类 java.lang.String类的使用 1.概述 String:字符串,使用一对""引起来表示. 1.String声明为final的,不可被继承 2.String ...
- MMDetection 快速开始,训练自定义数据集
本文将快速引导使用 MMDetection ,记录了实践中需注意的一些问题. 环境准备 基础环境 Nvidia 显卡的主机 Ubuntu 18.04 系统安装,可见 制作 USB 启动盘,及系统安装 ...
- chatsRoom Design Report
基于TCP实现聊天室 主要使用四个类 ChatClient类 使用BufferedReader 得到输入流,使用OutputStream得到输出流 实现读取服务器广播的消息和发送消息到 ...
- Python实验6--网络编程
题目1 1.编写程序实现基于多线程的TCP客户机/服务器程序. (1)创建服务器端套接字Socket,监听客户端的连接请求: (2)创建客户端套接字Socket,向服务器端发起连接: 服务器端套接字 ...
- (十四)json、pickle与shelve模块
任何语言,都有自己的数据类型,那么不同的语言怎么找到一个通用的标准? 比如,后端用Python写的,前端是js,那么后端如果传一个dic字典给前端,前端肯定不认. 所以就有了序列化这个概念. 什么是序 ...
- /etc/hosts文件
这个文件告诉主机哪些域名对应哪些ip,哪些主机名对应哪些ip. 一般也三个域 网络ip地址 主机名或域名 主机名别名 两部分的时候 主机ip地址和主机名