【字符串】KMP字符串匹配
Definition
\(KMP\)算法是一个字符串匹配算法。他接收两个字符串\(A,B\),返回\(B\)在\(A\)中出现的所有位置。
以下称需要被匹配的串\(A\)为主串,可能在主串中多次出现的串\(B\)为模式串。约定主串的长度为\(n\),模式串的长度为\(m\)。
朴素的想法显然是对使用两个指针\(i,j\)分别指向\(A,B\)。枚举\(i\)的位置,暴力右移\(j\)观察是否匹配。复杂度\(O(nm)\)。
考虑当一个位置失配的时候,如果主串的当前位置与模式串前面的某些位置相同,则可以直接跳到前面的位置,而不用从头开始。
举个例子:
主串:aaabbbc
模式串:aabbbc。
从主串第一个位置开始匹配,当\(i=2,j=2\)时,发现\(i+1\)与\(j+1\)失配,但是考虑完全不需要从第二个位置令\(i=2,j=1\)重新匹配,而是直接令\(j\)等于可以与\(i\)匹配的上一个前缀,即可重新匹配。所谓上一个前缀,设\(j\)被赋值为\(k\),则\(k\)满足主串[i-ki]==模式串[1k]。我们可以使用一个\(next\)数组直接预处理这个前缀,然后直接在失配时令模式串指针向前按照\(next\)数组向前跳即可。
考虑\(next\)数组的求法:把模式串错一位与自身匹配。j跳到的位置显然就是当前位置的\(next\)。
Example
Description
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
为了减少骗分的情况,接下来还要输出子串的前缀数组next。
Input
两行分别是\(s1\)和\(s2\)
Output
若干行,每行包含一个整数,表示s2在s1中出现的位置
接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。
Hint
字符串长度不超过\(10^6\)
Code
#include<cstdio>
#include<cstring>
#define rg register
#define ci const int
#define cl const long long
typedef long long int ll;
template <typename T>
inline void qr(T &x) {
rg char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
}
namespace IO {
char buf[120];
}
template <typename T>
inline void qw(T x,const char aft,const bool pt) {
if(x < 0) {x=-x,putchar('-');}
rg int top=0;
do {IO::buf[++top]=x%10+'0';} while(x/=10);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
}
template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T a) {return a < 0 ? -a : a;}
template <typename T>
inline void mswap(T &_a,T &_b) {
T _temp=_a;_a=_b;_b=_temp;
}
const int maxn = 1000010;
char s1[maxn],s2[maxn];
int nxt[maxn];
void KMP(char *a,char *b,int l1,int l2,bool pt) {
rg int i,j=0;
for(i=pt?1:2;i<=l1;++i) {
while(j&&(b[j+1] != a[i])) j=nxt[j];
if(b[j+1] == a[i]) ++j;
if(!pt) nxt[i]=j;
if(j == l2) {
qw(i-l2+1,'\n',true);
}
}
}
int main() {
scanf("%s\n%s",s1+1,s2+1);
int l1=strlen(s1+1),l2=strlen(s2+1);
KMP(s2,s2,l2,l2,false);
KMP(s1,s2,l1,l2,true);
for(rg int i=1;i<l2;++i) qw(nxt[i],' ',true);
qw(nxt[l2],'\n',true);
return 0;
}
【字符串】KMP字符串匹配的更多相关文章
- Luogu 3375 【模板】KMP字符串匹配(KMP算法)
Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...
- 洛谷P3375 [模板]KMP字符串匹配
To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...
- P3375 【模板】KMP字符串匹配
P3375 [模板]KMP字符串匹配 https://www.luogu.org/problemnew/show/P3375 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在 ...
- 洛谷—— P3375 【模板】KMP字符串匹配
P3375 [模板]KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next. (如 ...
- KMP字符串匹配 模板 洛谷 P3375
KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...
- {Reship}{KMP字符串匹配}
关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827
- 洛谷P3375 - 【模板】KMP字符串匹配
原题链接 Description 模板题啦~ Code //[模板]KMP字符串匹配 #include <cstdio> #include <cstring> int cons ...
- P3375 模板 KMP字符串匹配
P3375 [模板]KMP字符串匹配 来一道模板题,直接上代码. #include <bits/stdc++.h> using namespace std; typedef long lo ...
- KMP字符串匹配学习
KMP字符串匹配学习 牛逼啊 SYC大佬的博客
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
随机推荐
- Java or Python?测试开发工程师如何选择合适的编程语言?
很多测试开发工程师尤其是刚入行的同学对编程语言和技术栈选择问题特别关注,毕竟掌握一门编程语言要花不少时间成本,也直接关系到未来的面试和就业(不同企业/项目对技术栈要求也不一样),根据自身情况做一个相对 ...
- 2018 ACM-ICPC World Finals - Beijing F.Go with the Flow
先枚举所有的列长度 对于每种列长度,然后里面用dp算 #include <algorithm> #include <cmath> #include <cstdio> ...
- vue cli 3 +jquery
const webpack = require('webpack')module.exports = { // baseUrl type:{string} default:'/' // 将部署应用程序 ...
- Python基础灬dict&set
字典dict 字典使用键-值(key-value)存储,具有极快的查找速度. dict基本操作 取值 a_dict = {'name': 'jack', 'age': 18} print(a_dict ...
- BZOJ 1559 JSOI2009 密码 状压dp+AC自动机+搜索
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1559 分析: 这个题意真的是很**啊!!!直接说每一个字符串至少出现一次不就好了吗... ...
- 03 JAVA IO
java.io包中定义了多个流类型来实现输入输出功能,以不同的角度进行分类: 按数据流的方向不同可以分为输入流和输出流 按处理数据单位不通可以分为字节流和字符流 按照功能不同可以分为节点流和处理流 所 ...
- 第一阶段android学习笔记
1.学习<第一行代码> 第一个android项目: 项目的注意点,如创建项目时包名具有唯一性,在做项目的时候要手动改成Project模式.还知道了引用字符串的两种方式. AS项目的三种依赖 ...
- tomcat配置服务
1.在server中右键添加tomcat 2.双击tomcat打开配置窗口添加jvm参数 -Doapath="C:\exeye-workspace\exEyeWeb\oadoc" ...
- lintcode-392-打劫房屋
392-打劫房屋 假设你是一个专业的窃贼,准备沿着一条街打劫房屋.每个房子都存放着特定金额的钱.你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自 ...
- 解决CentOS安装redis局域网内无法访问的问题
redis4.0版本安装教程晚上非常多,随便贴出来一个:http://www.cnblogs.com/web424/p/6796993.html 安装完成后,在局域网内发现无法访问到redis.cen ...