字符串匹配 ?kmp : hash
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。
模板串P在模式串S中多次作为子串出现。
求出模板串P在模式串S中所有出现的位置的起始下标。
输入格式
第一行输入整数N,表示字符串P的长度。
第二行输入字符串P。
第三行输入整数M,表示字符串S的长度。
第四行输入字符串M。
输出格式
共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。
一个字符串匹配的模板, 求字符串A在字符串B中各次出现的位置, kmp分为两步:
1.对字符串A进行自我匹配, next[i]表示"A中以i结尾的非结尾前缀子串"与"A的前缀"能够匹配的最大长度, 即:
next[i] = max{j}, j < i 且 A[i - j + 1 ~ i] == A[1 ~ j]
当j不存在时, next[i] = 0;
2.对字符串A与B进行匹配, f[i]表示"B中以i结尾的非结尾前缀子串"与"A的前缀"能够匹配的最大长度, 即:
f[i] = max{j}, j < i 且 B[i - j + 1 ~ i] == A[1 ~ j]
引理:j是next[i]的一个候选项, 即j < i 且 A[i - j +1 ~ i] == A[1 ~ j], 则小于j的最大next[i]的候选项是next[j];
根据优化后计算的next数组 , 当f[i] = n(A的长度)时, i - n 则是A在B中出现的位置;
#include <bits/stdc++.h> using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;
const double eps = 1e-5; template < typename T > inline void read(T &x) {
x = 0; T ff = 1, ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
} int n, m, next[MAXN], f[MAXN];
char P[MAXN], M[MAXN]; int main() {
read(n);
scanf("%s", P + 1);
read(m);
scanf("%s", M + 1);
for(int i = 2, j = 0; i <= n; ++i) {
while(j && P[j + 1] != P[i]) j = next[j];
if(P[j + 1] == P[i]) ++j;
next[i] = j;
}
for(int i = 1, j = 0; i <= m; ++i) {
while(j && (j == n || P[j + 1] != M[i])) j = next[j];
if(P[j + 1] == M[i]) ++j;
f[i] = j;
if(f[i] == n) {
write(i - n);
putchar(' ');
}
}
return 0;
}
其实用hash来做更加显然, 在O(N)的时间内预处理字符串的hash值, 枚举B中每个位置i(n <= i <= m) ,检查A的hash值和B的子串B[i - n + 1 ~ i] 是否相同即可
#include <bits/stdc++.h> using namespace std; typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;
const double eps = 1e-5; template < typename T > inline void read(T &x) {
x = 0; T ff = 1, ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -1;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
} int n, m;
unsigned long long x, q[MAXN], a[MAXN];
char p[MAXN], s[MAXN]; int main() {
read(n);
scanf("%s", p + 1);
read(m);
scanf("%s", s + 1);
for(int i = 1; i <= n; ++i) {
x = x * 131 + (p[i] - 'a' + 1);
}
q[0] = 1;
for(int i = 1; i <= m; ++i) {
q[i] = q[i - 1] * 131;
a[i] = a[i - 1] * 131 + (s[i] - 'a' + 1);
}
for(int i = n; i <= m; ++i) {
if(a[i] - a[i - n] * q[n] == x) {
write(i - n);
putchar(' ');
}
}
return 0;
}
字符串匹配 ?kmp : hash的更多相关文章
- 字符串匹配KMP算法详解
1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...
- 字符串匹配-KMP
节选自 https://www.cnblogs.com/zhangtianq/p/5839909.html 字符串匹配 KMP O(m+n) O原来的暴力算法 当不匹配的时候 尽管之前文本串和模式串已 ...
- zstu.4194: 字符串匹配(kmp入门题&& 心得)
4194: 字符串匹配 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 206 Solved: 78 Description 给你两个字符串A,B,请 ...
- 字符串匹配KMP算法
1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- 字符串匹配KMP算法的C语言实现
字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...
- 字符串匹配KMP算法的讲解C++
转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...
- 字符串匹配KMP算法(转自阮一峰)
转自 http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字符串匹配是计算 ...
- 【Foreign】字符串匹配 [KMP]
字符串匹配 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 3 3 6 3 1 2 1 2 ...
- 【Luogu P3375】字符串匹配KMP算法模板
Luogu P3375 模式串:即题目中的S2所代表的意义 文本串:即题目中的S1所代表的意义 对于字符串匹配,有一种很显然的朴素算法:在S1中枚举起点一位一位匹配,失配之后起点往后移动一位,从头开始 ...
随机推荐
- Spring Boot中有多个@Async异步任务时,记得做好线程池的隔离!
通过上一篇:配置@Async异步任务的线程池的介绍,你应该已经了解到异步任务的执行背后有一个线程池来管理执行任务.为了控制异步任务的并发不影响到应用的正常运作,我们必须要对线程池做好相应的配置,防止资 ...
- IP 地址无效化
给你一个有效的 IPv4 地址 address,返回这个 IP 地址的无效化版本. 所谓无效化 IP 地址,其实就是用 "[.]" 代替了每个 ".". 示例 ...
- php 设计模式 --组合器模式
PHP 开启错误显示并设置错误报告级别 ini_set('error_reporting', E_ALL); ini_set('display_errors', 'on'); 目的:分级处理:整体 ...
- P3214-[HNOI2011]卡农【dp】
正题 题目链接:https://www.luogu.com.cn/problem/P3214 题目大意 一个由\(1\sim n\)的所有整数构成的集合\(S\),求出它的\(m\)个不同非空子集满足 ...
- P5369-[PKUSC2018]最大前缀和【状压dp】
正题 题目链接:https://www.luogu.com.cn/problem/P5369 题目大意 一个数列\(a\)的权值定义为\(max\{\sum_{i=1}^ka_i\}(k\in[1,n ...
- WPF进阶技巧和实战03-控件(5-列表、树、网格01)
列表控件 ItemsControl为列表项控件定义了基本功能,下图是ItemsControl的继承关系: 在继承自ItemsControl类的层次结构中,还显示了项封装器(MenuItem.TreeV ...
- Excel备忘录
1. 导入文本文件(.txt) 2. 排序 3. 批量填充空白 选定区域,Ctrl+G,定位,空值. 输入内容,Ctrl+Enter. 4. 清除无法修改的背景色. 5. 身份证号 数字精度为15位, ...
- DOC命令和批处理命令
本文章以极简的方式展现,相信能够浏览到这篇文章的人都对批命令有了一定的了解,我不会把文章写的长篇大论 重要!!! (命令/?)查看帮助文档 (命令/help)查看详细帮助文档 附:思维导图 批处理编程 ...
- 小程序 rich-text 处理显示
VIEW <view class="richText"> <rich-text nodes="{{richTextHTML}}" bindta ...
- 重新整理 .net core 周边阅读篇————AspNetCoreRateLimit 之规则[二]
前言 本文和上文息息相关. https://www.cnblogs.com/aoximin/p/15315102.html 是紧接着上文invoke来书写的,那么现在来逐行分析invoke到底干了啥. ...