Hash——字符串匹配(求s1在s2中出现的次数)
题目描述:
这是一道模板题。
给定一个字符串 A 和一个字符串 B ,求 B 在 A 中的出现次数。A 和 B中的字符均为英语大写字母。
求A 在 B 中出现了几次。(可重叠)
样例输入:
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
样例输出:
1
3
0
首先要知道什么是字符串hash(滚动哈希):
单哈希可以O(m)的时间计算长度为m的字符串的哈希值,但对于本题,总的时间复杂度没有改观。时间会爆。
这时我们就需要一个叫做滚动哈希的优化技巧。
我们选取两个合适的互质常数b和h(b<h),假设字符串C=c1c2……cm,那么我们定义哈希函数:H(C)=(c1bm-1+c2bm-2+……+cmb0) mod h 。
正常数字是十进制的,这里b是基数,相当于把字符串看做是b进制数。
这一过程是递推计算的,设H(C,k)为前k个字符构成的字符串的哈希值,则:(以下均不考虑取模的情况)
H(C,k+1)=H(C,k)× b + ck+1
字符串哈希,通常题目要求的是判断主串的一段字符串与另一个匹配串是否匹配,即判断字符C=c1c2……cm从位置k+1开始的长度为n的子串C'=ck+1ck+2……ck+n的哈希值与另一匹配串S=s1s2……sn的哈希值是否相等,则:
H(C')=H(C,k+n) - H(C,k) × bn
于是我们只要预求得b,就能在O(1)时间内得到任意字符串的字符串的子串哈希值,从而完成字符串匹配,那么上述字符串匹配问题的算法复杂度就为O(n+m)。
在实现算法时,可以利用32位或64位无符号整数计算hash值(如:unsigned long long),并取h=232或h=264,通过自然溢出省去取模运算。
——By《一本通》
那么本题就可以用上述方式AC了(书上代码有bug,需自己改动)
AC代码如下:
#include<cstring>
#include<cstdio>
using namespace std;
#define ULL unsigned long long
#define K 103
int N;
char s1[], s2[];
ULL f[],l1,l2,t;
ULL a[];
ULL get(int x,int y)
{
return f[y]-f[x-]*a[y-x+];
}
int main()
{
//freopen("字符串匹配(求s1在s2中出现的次数).in","r",stdin);
//freopen("字符串匹配(求s1在s2中出现的次数).out","w",stdout);
scanf("%d",&N);
a[]=;
for(int i=;i<=;++i)//预处理出a^n
a[i]=a[i-]*K;
for(int i=;i<=N;++i)
{
int ans();t=;
scanf("%s%s",s2+,s1+);
l1=strlen(s1+);l2=strlen(s2+);
for(int j=;j<=l1;++j)
f[j]=f[j-]*K+(s1[j]-'A');//计算主串的滚动哈希值
for(int j=;j<=l2;++j)
t=t*K+(s2[j]-'A');//计算匹配串的哈希值
for (int j=;j+l2-<=l1;++j)
{
if(get(j,j+l2-)==t)//枚举起点为i,长度为n的子串,判断与匹配串是否匹配
ans++;
}
printf("%d\n",ans);//输出
}
return ;
}
Hash——字符串匹配(求s1在s2中出现的次数)的更多相关文章
- 选拔赛 hash 字符串匹配 哈希算法(白书p374)
hash Description dr所在国度的有个奇怪的规定:他们的字母不是a~z,而是用1~1000表示. 利用这个奇怪的规定,dr想出了一个好玩的游戏:首先给出n个字符串(当然每个字符用1~ ...
- JAVA常见算法题(三十三)---求子串在字符串中出现的次数
计算某字符串中子串出现的次数. public static void main(String[] args) { String s1 = "adcdcjncdfbcdcdcd"; ...
- hdoj 4552 怪盗基德的挑战书【求前缀在字符串中出现的次数之和】
怪盗基德的挑战书 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Su ...
- 字符串匹配--Regex
利用Regix实现字符串匹配 Eg:匹配嵌入到[]中的字符 string pattern = Regex.Escape("[") + "(.*?)]"; str ...
- C语言:求n(n<10000)以内的所有四叶玫瑰数。-将字符串s1和s2合并形成新的字符串s3,先取出1的第一个字符放入3,再取出2的第一个字符放入3,
//函数fun功能:求n(n<10000)以内的所有四叶玫瑰数并逐个存放到result所指数组中,个数作为返回值.如果一个4位整数等于其各个位数字的4次方之和,则称该数为函数返回值. #incl ...
- 浅谈Hash在多个字符串匹配类型问题中的应用
在生活中们有时会遇到一些有关字符串匹配的问题. 这时打暴力往往显得很愚蠢,效率低下. 所以就需要一些算法和数据结构来提高效率. Hash Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把 ...
- squeeze(s1,s2),将字符串s1中任何与字符串s2中匹配的字符都删除
void squeeze(char a[],char b[]) { //要实现把s2的任意字符如果出现的话就在s1中删除 //1.首先判断s1[j]==s2[i]&&s1[j]=='\ ...
- TCPL学习笔记:编写expand(s1, s2),将字符串s1中类似于a-z一类的速记符号在s2中扩充完整。可以处理大小写及字符,以及a-b-c, a-z0-9以及-a-z等多种情况。
话不多说,看代码: #include <stdio.h> #include <stdlib.h> int main(void) { ] = "a-z0-9hahah- ...
- 【模板】字符串匹配的三种做法(Hash、KMP、STL)
题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 输入输出格式 输入格式: 第一行为一个字符串,即为s1 第二行为一个字符串,即为s2 输出格式: 1行 ...
随机推荐
- 注意!list和array是不同的
python中的list是python的内置数据类型,list中的数据类型不必相同的,而array的中的数据类型必须全部相同. numpy中封装的array有很强大的功能,里面存放的都是相同的数据类 ...
- Install kubernetes without yum
下载最新版本: https://github.com/kubernetes/kubernetes/releases 下载kubernetes.tar.gz即可 解压缩后到cluster目录下 执行ge ...
- 给web项目整合富文本编辑器
给jsp页面整合富文本编辑器下载——删除多余的组件——加入到项目中——参照案例来完成整合步骤:1. 解压zip文件,将所有文件复制到Tomcat的webapps/kindeditor目录下. 2. 将 ...
- 【移动端】js禁止页面滑动与允许滑动
禁止页面滑动 通常静止滑动方案:(阻止滑动事件) window.ontouchmove=function(e){ e.preventDefault && e.preventDefaul ...
- 使用v-for指令渲染列表
v-for:对集合或对象进行遍历: 使用v-for对数组遍历时: 效果如下: 代码: <script> window.onload= () =>{new Vue({ el:'#two ...
- gdb调试问题汇总
1. 宏调试 在GDB下,我们无法print宏定义,因为宏是预编译的.但是我们还是有办法来调试宏,这个需要GCC的配合. 在GCC编译程序的时候,加上-ggdb3参数,这样,你就可以调试宏了.另外,你 ...
- 【ASP.Net MVC3 】使用Unity 实现依赖注入
转载于:http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html 家人身体不太好,好几天没在园子里发帖了. 新项目还是要用M ...
- ssh-keygen 不是内部或外部命令
如何处理呢? 1.找到Git/usr/bin目录下的ssh-keygen.exe(如果找不到,可以在计算机全局搜索) 2.属性-->高级系统设置-->环境变量-->系统变量,找到Pa ...
- sudo env
$ sudo echo "Defaults env_keep=\"PATH PYTHONPATH LD_LIBRARY_PATH CAFFE_ROOT\"& ...
- rabbitmq install erlang faild
我安装的时候莫名的出现这2个错误 No Presto metadata available for rabbitmq-erlangwarning: /var/cache/yum/x86_64/7/ra ...