单模式串匹配----浅谈kmp算法
flag:字符串小结。
模式串匹配,顾名思义,就是看一个串是否在另一个串中出现,出现了几次,在哪个位置出现;
p.s. 模式串是前者,并且,我们称后一个 (也就是被匹配的串)为文本串;
在这篇博客的代码里,s1均为文本串,s2均为模式串;
一般地,文本串长度不小于匹配串;(否则无意义)
很显然可以得到一个暴力的做法 :
for i : ~lenth_of_s1 {//枚举匹配串在文本串中的开始位置
for j : ~lenth_of_s2
if(s2[j]!=s1[i+j-]) break;
if j>lenth_of_s2 //在循环结束前没有break
output : i
}
时间复杂度:O ( TLE ) ------ O (N+M) ~ O(N*M)
所以需要一个更优的算法;
可以发现,在枚举匹配串在文本串中的开始位置时,有很多步骤是无效的,因为匹配串的第一个字符 很有可能和当前枚举到的开始位置 不同;
所以可以优化这个过程,每次改变开始位置时,直接移动到下一个和匹配串第一个字符相同的位置 (类似于链表;
int next[N], pos=-;
char head = s2[]; for i : lenth_of_s1~
if s1[i]==head {
next[i] = pos;
pos = i;
}
next[] = pos; for i = next[] ; i != - ; i = next[i] {
for j : ~lenth_of_s2
if(s2[j]!=s1[i+j-]) break;
if j>lenth_of_s2 //在循环结束前没有break
output : i
}
这个做法看起来很强,实际上很容易被卡成O (n^2);
比如说 :s1 :sssssssssssssa, s2 : sssb;
由于并没有利用所有已经匹配过的部分,所以仍然会T;
于是,就有了KMP算法。
p.s. i表示当前在文本串中枚举到的位置,j表示模式串中的;
在s1[ i ] != s2 [ j ]时,将 j 移动到一个在 j 之前的位置k 使得 s2[ 1 ]~s2[ k ] 与 s2[ j-k+1 ]~s2[ j ]完全相同,那么时间复杂度就是O (N+M) 的了;
p.s. 因为 i , j 两个指针最多移动N+M次;
给一个写模板的链接 :https://www.luogu.org/problemnew/show/P3375
贴代码 :
// luogu-judger-enable-o2
// 15owzLy1
//luogu3375_kmp.cpp
//2018 10 02 17:27:50
#include <cstdio>
#include <cstring>
typedef long long ll;
typedef double db;
using namespace std; const int N = ;
int next[N], la, lb;
char a[N], b[N]; template<typename T>inline void read(T &x_) {
x_=;bool f_=;char c_=getchar();
while(c_<''||c_>''){f_|=(c_=='-');c_=getchar();}
while(c_>=''&&c_<=''){x_=(x_<<)+(x_<<)+(c_^);c_=getchar();}
x_=f_?-x_:x_;
} inline void get_next() {
int j=;
for(int i=;i<=lb;i++) {
while(j&&b[j+]!=b[i]) j=next[j];
if(b[j+]==b[i]) ++j;
next[i]=j;
}
} inline void kmp() {
int j=;
for(int i=;i<=la;i++) {
while(j&&a[i]!=b[j+]) j=next[j];
if(b[j+]==a[i]) ++j;
if(j==lb)
printf("%d\n", i-j+);
}
} int main() {
#ifndef ONLINE_JUDGE
freopen("luogu3375_kmp.in","r",stdin);
freopen("luogu3375_kmp.out","w",stdout);
#endif
scanf("\n%s%s", a+, b+); la=strlen(a+), lb=strlen(b+);
get_next();
kmp();
for(int i=;i<=lb;i++) printf("%d ", next[i]);
puts("");
return ;
}
单模式串匹配----浅谈kmp算法的更多相关文章
- 浅谈KMP算法及其next[]数组
KMP算法是众多优秀的模式串匹配算法中较早诞生的一个,也是相对最为人所知的一个. 算法实现简单,运行效率高,时间复杂度为O(n+m)(n和m分别为目标串和模式串的长度) 当字符串长度和字符集大小的比值 ...
- 浅谈KMP算法
一.介绍 烤馍片KMP算法是用来处理字符串匹配问题的.比如说给你两个字符串A,B,问B是不是A的子串? 比如,eg就是aeggx的子串 一般讲字符串A称为主串,用来匹配的B串称为模式串 定义n为字符串 ...
- 【字符串算法3】浅谈KMP算法
[字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述 [字符串算法3]KMP算法 Part1 理解KMP的精髓和思想 其实KM ...
- 浅谈KMP算法——Chemist
很久以前就学过KMP,不过一直没有深入理解只是背代码,今天总结一下KMP算法来加深印象. 一.KMP算法介绍 KMP解决的问题:给你两个字符串A和B(|A|=n,|B|=m,n>m),询问一个字 ...
- 【文文殿下】浅谈KMP算法next数组与循环节的关系
KMP算法 KMP算法是一种字符串匹配算法,他可以在O(n+m)的时间内求出一个模式串在另一个模式串下出现的次数. KMP算法是利用next数组进行自匹配,然后来进行匹配的. Next数组 Next数 ...
- 浅谈 KMP 算法
最近在复习数据结构,学到了 KMP 算法这一章,似乎又迷糊了,记得第一次学习这个算法时,老师在课堂上讲得唾沫横飞,十分有激情,而我们在下面听得一脸懵比,啥?这是个啥算法?啥玩意?再去看看书,完全听不懂 ...
- 浅谈分词算法(5)基于字的分词方法(bi-LSTM)
目录 前言 目录 循环神经网络 基于LSTM的分词 Embedding 数据预处理 模型 如何添加用户词典 前言 很早便规划的浅谈分词算法,总共分为了五个部分,想聊聊自己在各种场景中使用到的分词方法做 ...
- 浅谈分词算法(4)基于字的分词方法(CRF)
目录 前言 目录 条件随机场(conditional random field CRF) 核心点 线性链条件随机场 简化形式 CRF分词 CRF VS HMM 代码实现 训练代码 实验结果 参考文献 ...
- 浅谈分词算法(3)基于字的分词方法(HMM)
目录 前言 目录 隐马尔可夫模型(Hidden Markov Model,HMM) HMM分词 两个假设 Viterbi算法 代码实现 实现效果 完整代码 参考文献 前言 在浅谈分词算法(1)分词中的 ...
随机推荐
- 理解mysql执行多表联合查询
阅读目录 一:inner join(内连接) 二:left join(左连接) 三:right join(右连接) 四:cross join(交叉连接) 五:union操作 六:node+mysql ...
- 2018 C++ Teaching Assistant Summary
期末考结束后就留校开始了科研,最近刚回家休息了两三天,整理了思绪,准备补上这一篇拖延了一个多月的助教小结. 早在一年多前我上栋哥这门课时,我就十分乐意给予同学帮助,无论是技术上的,还是说思想上的(也可 ...
- spring boot 操作MySQL pom添加的配置
1 在项目中的pom.xml配置文件添加依赖 <!--MySQL依赖 --> <dependency> <groupId>mysql</groupId> ...
- Python基础知识3-函数、参数及参数解构
函数 函数定义.调用 函数参数 函数参数默认参数 函数参数默认值 可变参数 keyword-only参数 可变参数和参数默认值 函数参数 参数解构 练习: #编写一个函数,能够接受至少2个参数 def ...
- "unexpected console statement” in Node.js
.eslintrc.js module.exports = { rules: { 'no-console': 'off', }, };
- nginx.conf配置详解
######Nginx配置文件nginx.conf中文详解##### #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_ ...
- Lodop简短问答客户反馈篇 及排查步骤 及注册相关
A.http下打印图片正常,https下打印图片是××.(有的客户端可以,有的不可以)重置ie浏览器试试.客户反馈:(和ie浏览器的设置有关)intenet选项--高级里,我调整为和能打印出图片的电脑 ...
- SQL 中左连接与右链接的区别
在微信公众号中看到的sql左连接与右链接的总结,这个图总结的很好,所以单独收藏下:
- webpack学习记录-认识loader(二)
Loader 就像是一个翻译员,能把源文件经过转化后输出新的结果,并且一个文件还可以链式的经过多个翻译员翻译. loader参考文章:https://webpack.docschina.org/loa ...
- Count on a tree SPOJ - COT (主席树,LCA)
You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer ...