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行 ...
随机推荐
- 1、CentOS部署Java开发环境
一.安装jdk jdk下载地址:http://www.Oracle.com/technetwork/java/javase/downloads/jdk-6u31-download-1501634.h ...
- [转载]FileStream读写文件
FileStream读写文件 FileStream类:操作字节的,可以操作任何的文件 StreamReader类和StreamWriter类:操作字符的,只能操作文本文件. 1.FileStream类 ...
- 【独家】终生受用的Redis高可用技术解决方案大全
最近很多朋友向我咨询关于高可用的方案的优缺点以及如何选择合适的方案线上使用,刚好最近在给宜人贷,光大银行做企业内训的时候也详细讲过,这里我再整理发出来,供大家参考,如有不妥之处,欢迎批评指正,也欢迎推 ...
- linux下的ifconfig命令
ifconfig工具不仅可以被用来简单地获取网络接口配置信息,还可以修改这些配置. 1.命令格式: ifconfig [网络设备] [参数] 2.命令功能: ifconfig 命令用来查看和配置网络设 ...
- Kattis之旅——Chinese Remainder
Input The first line of input consists of an integers T where 1≤T≤1000, the number of test cases. Th ...
- git学习总结 - 纯命令
全局安装git: npm intall git -g 查看git版本: git --version 进入目录,初始化git: 若在目录中使用上一个,不在目录中使用下一个. //已有目录: git in ...
- ES6知识整理(7)--Set和Map数据结构
(文章会同步到博客园,技术类文章还是该让搜索引擎察觉比较好) Set构造函数 初始化一个值不重复的数组,适合做数组去重. 2种数组去重的方法: 这里再说下Array.from(),表示以一个类数组|| ...
- Solr导入MySQL数据之dataimport-handler
Solr不借助手动JSolr编程情况下也可以将Mysql的数据导入到Solr中.实现方式是安装dataimport-Handler从关系数据库将数据导入到索引库. 1.向SolrCore中加入jar包 ...
- 【题解】Luogu UVA1411 Ants
原题传送门 博客里对二分图匹配的详细介绍 这道题是带权二分图匹配 用的是KM算法 我们要知道一个定理:要使线段没有相交,要使距离总和最小 我们先把任意一对白点.黑点的距离算一下 然后运用KM算法 因为 ...
- 集合框架-Collection与List集合
对象数组的内存图解: 集合的继承体系图解: * 数组和集合的区别? * A:长度区别 * 数组的长度固定 * 集合长度可变 * B:内容不同 * 数组存储的是同一种类型的元素 * 而集合可以存储不同类 ...