题目描述

如题,给出两个字符串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)的更多相关文章

  1. js函数只执行一次,函数重写,变量控制与闭包三种做法

    一.情景需求 调用后台接口需要附带token信息,那么在每个请求的头部添加token的做法就不太优雅了:一个网站请求100次,那就得写添加100次token,假设某天接口有所变动,改起来就十分麻烦了. ...

  2. codevs 2924 数独挑战 x(三种做法+超详细注释~)

    2924 数独挑战  时间限制: 1 s  空间限制: 1000 KB  题目等级 : 钻石 Diamond   题目描述 Description “芬兰数学家因卡拉,花费3个月时间设计出了世界上迄今 ...

  3. 多表连接的三种方式 HASH MERGE NESTED

    多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP------------------------------------------------------20 ...

  4. sdut 2125串结构练习--字符串匹配【两种KMP算法】

    串结构练习——字符串匹配 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sduto ...

  5. JavaScript中交换两个变量的值得三种做法(代码实现)

    javascript在编程时经常会涉及到如何交换两个变量的值,例如常见的冒泡排序,快速排序等:下面我讲根据自己近期所学总结几种常见的交换两个变量值的方法: 方法一:借助第三方变量交换两个变量的值 va ...

  6. 三种做法:BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster

    目录 题意 思路 AC_Code1 AC_Code2 AC_Code3 参考 @(bzoj 2780: [Spoj]8093 Sevenk Love Oimaster) 题意 链接:here 有\(n ...

  7. list 删除一个元素的三种做法--python

    我们以一个字符串为元素类型的 list 为例,进行列表元素的删除: l = ['no surfing', 'flippers'] 法一:remove(val) >>> l.remov ...

  8. Python 技巧(三)—— list 删除一个元素的三种做法

    我们以一个字符串为元素类型的 list 为例,进行列表元素的删除: >>> l = ['no surfing', 'flippers'] 1 法一:remove(val) >& ...

  9. 求解区间问题的三种做法的区别 线段树、树状数组、RMQ

    树状数组主要用于计算区间的和,在区间元素修改值的时候能够快速修改而不是以O(n)的复杂度进行修改: 线段树是把区间以树的形式分拆为若干个小区间,每个小区间存的都有一个值(树状数组的元素存的是区间值), ...

随机推荐

  1. java导出Excel定义导出模板

    在很多系统功能中都会有Excel导入导出功能,小编采用JXLS工具,简单.灵活. JXLS是基于 Jakarta POI API 的Excel报表生成工具,它采用标签的方式,类似于jsp页面的EL表达 ...

  2. COPD——团队项目测试心得

    写在前面: 测试结束了,也要和项目说拜拜了~这一学期时间飞快,痛并快乐着,想想人生如果是个软件,那我们用多长时间在做测试呢?恐怕是一辈子.很多人忙着追逐,却很少人能停下来审视自己,那些时常自省的,常能 ...

  3. 关于js数组的简单复制

    var a=[]; a.push(1); a.push(2); a.push(3); var b=a; b[0]=4; alert(a);//4,2,3 alert(b);//4,2,3 这种写法由于 ...

  4. windows7 下jdk1.8 改为 1.7过程,及环境变量配置;

    一. 安装完成后 当然是配置环境变量: JAVA_HOME 是我们以后用到jdk所在位置的内容时为了方便,给jdk起的名字,也是java程序约定的变量名,如果没有,当你在cmd 输入 java  ja ...

  5. 接口自动化:pytest----环境搭建

    出处:https://www.cnblogs.com/yoyoketang/p/9356693.html 前言: python鄙视链:pytest 鄙视 > unittest 鄙视 > r ...

  6. c++ string 转double

    #include <iostream>#include <sstream> //使用stringstream需要引入这个头文件using namespace std; Type ...

  7. centos 6.5 安装 tomcat8 及性能优化_虚拟主机

    Tomcat服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP程序的首选. Tomcat和Nginx.Apa ...

  8. OpenGL之shader着色器的应用,三色渐变的三角形

    学习自: https://learnopengl-cn.github.io/01%20Getting%20started/05%20Shaders/#_7 首先放一张效果图: 本次教程,将着色器单独定 ...

  9. 关于JDBC和连接池我学到的(转载保存)

    1.JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模 ...

  10. nginx 配置本地https(免费证书)

    Linux系统下生成证书 生成秘钥key,运行: $ openssl genrsa -des3 -out server.key 20481会有两次要求输入密码,输入同一个即可 输入密码 然后你就获得了 ...