【模板】字符串匹配的三种做法(Hash、KMP、STL)
题目描述
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
输入输出格式
输入格式:
第一行为一个字符串,即为s1
第二行为一个字符串,即为s2
输出格式:
1行,包含若干整数,表示s2在s1中出现的位置,中间用空格隔开。
输入输出样例
输入样例#1: 输出样例#1:
ABABABC 1 3
ABA
很明显,这道题可以用暴力求解字符串匹配。即枚举起点,然后判断是否为子串。时间复杂度为$O(len^2)$.复杂度明显超时。
Hash:
一种用正确率换取时间的算法,可以把每个字符串看作是一个b进制下的数,求出它在10进制下的值,然后在与几个质数取模,得到在(long long) | (int)范围内可储存的值,这种情况下我们认为同一hash值的字符串相同。
在一般情况下,不会有人专门卡Hash,所以也可以不取模,定义一个(unsigned long long) 让它自然溢出。
思路如下:预处理出每一个$b^i$和A串的前缀Hash,枚举A串的起点,求出从$i$到$i+len(B)$的hash值,与B的hash值比较,时间复杂度是$O(n)$。
代码如下:
#include<bits/stdc++.h>
const int b = ;
typedef unsigned long long pmod;
char s1[], s2[];
pmod sum[];
pmod p[];
int main(){
p[] = , sum[] = ; pmod s = ;
for(int i=; i<; i++)//预处理
p[i] = p[i-]*b;
scanf("%s%s", s1+, s2+);
int n = strlen(s1+), m = strlen(s2+), cnt=;
for(int i=; i<=n; i++)//预处理出A串的前缀Hash值
sum[i] = sum[i-]*b+(pmod)(s1[i]-'A');
for(int i=; i<=m; i++)
s = s*b+(pmod)(s2[i]-'A');
for(int i=; i<=n-m; i++)//枚举起点
if(s == sum[i+m]-sum[i]*p[m]) cnt++;
printf("%d\n", cnt);
return ;
}
KMP:
将A串称为模式串,B串成为主串。
枚举每个模式串终点$i$,判断主串能匹配的长度$j$。$j$同时为主串上匹配的位置
匹配成功$i++, j++$.
在简单的一次匹配失败后,我们会想将模式串尽量的右移和主串进行匹配。右移的距离在KMP算法中是如此计算的:在已经匹配的模式串子串中,找出最长的相同的前缀和后缀,然后移动使它们重叠。
也就是将匹配长度$j$由当前位置变为上一个可以匹配的位置
如此可以在$O(n)$的时间复杂度内完成匹配
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = ;int next[N];char a[N], b[N];
int main() {
scanf("%s%s", a+, b+);
int n=strlen(a+), m=strlen(b+), j=;
next[]=;
for(int i=; i<m; i++) {
while(j> && b[j+] != b[i+]) j=next[j];
if(b[i+] == b[j+]) j++;
next[i+]=j;
}j=;
for(int i=; i<n; i++) {
while(j> && b[j+] != a[i+]) j=next[j];
if(a[i+] == b[j+]) j++;
if(j==m) {printf("%d\n", i-j+, i, j);j=next[j];}
}
for(int i=;i<=m;i++) printf("%d ", next[i]);
return ;
}
STL:
c++最强大的功能就是STL,它可以使代码很简洁,但同时会降低代码的效率(因为频繁的调用),但是,考试中使用STL也是一种好的办法,可以大大降低编程的时间。
本题可以使用STL中string的find()函数和其中表示string类型允许的最大值npos。
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
int main(){
string s, c;
int ans=, p=-;
getline(cin, s);
getline(cin, c);
while((p=s.find(c, p+))!=string::npos) ans++;
printf("%d", ans);
return ;
}
非常简洁。
【模板】字符串匹配的三种做法(Hash、KMP、STL)的更多相关文章
- js函数只执行一次,函数重写,变量控制与闭包三种做法
一.情景需求 调用后台接口需要附带token信息,那么在每个请求的头部添加token的做法就不太优雅了:一个网站请求100次,那就得写添加100次token,假设某天接口有所变动,改起来就十分麻烦了. ...
- codevs 2924 数独挑战 x(三种做法+超详细注释~)
2924 数独挑战 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 钻石 Diamond 题目描述 Description “芬兰数学家因卡拉,花费3个月时间设计出了世界上迄今 ...
- 多表连接的三种方式 HASH MERGE NESTED
多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP------------------------------------------------------20 ...
- sdut 2125串结构练习--字符串匹配【两种KMP算法】
串结构练习——字符串匹配 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sduto ...
- JavaScript中交换两个变量的值得三种做法(代码实现)
javascript在编程时经常会涉及到如何交换两个变量的值,例如常见的冒泡排序,快速排序等:下面我讲根据自己近期所学总结几种常见的交换两个变量值的方法: 方法一:借助第三方变量交换两个变量的值 va ...
- 三种做法:BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster
目录 题意 思路 AC_Code1 AC_Code2 AC_Code3 参考 @(bzoj 2780: [Spoj]8093 Sevenk Love Oimaster) 题意 链接:here 有\(n ...
- list 删除一个元素的三种做法--python
我们以一个字符串为元素类型的 list 为例,进行列表元素的删除: l = ['no surfing', 'flippers'] 法一:remove(val) >>> l.remov ...
- Python 技巧(三)—— list 删除一个元素的三种做法
我们以一个字符串为元素类型的 list 为例,进行列表元素的删除: >>> l = ['no surfing', 'flippers'] 1 法一:remove(val) >& ...
- 求解区间问题的三种做法的区别 线段树、树状数组、RMQ
树状数组主要用于计算区间的和,在区间元素修改值的时候能够快速修改而不是以O(n)的复杂度进行修改: 线段树是把区间以树的形式分拆为若干个小区间,每个小区间存的都有一个值(树状数组的元素存的是区间值), ...
随机推荐
- ProtocolBuffer for Objective-C Mac运行环境配置
上班第4天,上司让我研究Google的Protocol Buffer,对于我这个小白来说这是一大难题.结合了一下网上资料,用了几个小时的时间,终于搞明白了.做个笔记,也当做资料给大家分享一下. 什么是 ...
- eureka注册中心列表页面加账号和密码
正常情况下,注册中心服务启动后,页面是这样的,如下图所示 这样的话,如果注册中心不再内网地址下,有可能就会泄露所有的服务地址信息,增加受攻击的风险,针对这个问题咱们可以这样解决 首先注册中心pom.x ...
- python列表的学习笔记
列表的操作 第一个例子: #names = "zhangyang guyun xiangpeng xuliangchen" #通过空格或逗号存变量 names = [" ...
- LeetCode 145 二叉树的后序遍历(非递归)
题目: 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路: 1 ...
- List集合联系
创建一个List,在List 中增加三个工人,基本信息如下: 姓名 年龄 工资 zhang3 18 3000 li4 25 3500 wang5 22 3200 a) 在li4 之前插入一个工人,信息 ...
- SoapUI--the use of Script Library
SoapUI--the use of Script Library 有两种方法在soapUI中引用自己的groovy脚本库. 方法一:把自己的script folder放到soapUI install ...
- poj1002总结
1.之前一直是runtime error,没有找出具体原因,把冒牌排序改成了合并排序,当输入是100000行时,从大约10s变到1s内 2.感觉是atoi指针导致的,当判断atoi的入参不为NULL时 ...
- django 模板 (ああああああああ!かぴ)
一 常用 1. {{ 不存在 | default : "xx" }} 2. {{ name | length }} 3. {{ xx | slice "1:-1" ...
- ubuntu的安装与vim(部分)文件的配置
Ubuntu的安装与vim相关的配置 虚拟机环境的安装(先说说虚拟机的安装步骤把) 对于安装ubuntu来讲不是很难掌握,但是在Linux系统虚拟机下提供了很多便利的手段,而要配置一个顺手的虚拟机环境 ...
- uploadfy 图片/视频上传
JS引入 <link href="../../Scripts/uploadify/uploadify.css" rel="stylesheet" /> ...