滚动Hash

假设字符串\(C=c_1*c_2*...c_m\),定义Hash函数\(H(C)=(C_1*b^{m-1}+C_2*b^{m-2}+...C_m*b^{0})mod\; h\)

从k开始长为|m|的子串的hash值转移到从k+1开始长为|m|的字串的hash值的转移公式为 :$$H(S[k+1..k+m]=(H(S[k..k+m-1])b-s_kb^m+s_{k+m}$$

基数使用1e7以上的素数减少冲突,使并且用\(ull\)自然溢出代替取模运算,滚动Hash的期望复杂度为\(O(n+m)\)。

题目链接:

给出字符串S和T,求S在T中出现的次数。

AcCode:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef unsigned long long ull;
const ull B = 100000007;//Hash基数
int n;
char w[10010],t[1000010];
int main(){
scanf("%d",&n);
while(n--){
scanf("%s%s",w,t);
int lw=strlen(w),lt=strlen(t);
ull wh=0,th=0,base=1;
//计算W和T串从第一位开始的长度为lenw的Hash值
for(int i=0;i<lw;i++)
wh=wh*B+w[i],th=th*B+t[i]; //计算base的lenw次方,用于Hash转移
for(int i=0;i<lw;++i)base*=B; int ans=0;
for(int i=0;i+lw<=lt;++i){
if(wh==th)ans++;
if(i+lw<lt)th=th*B+t[i+lw]-t[i]*base;//这里减法可能会溢出,但是利用无符号数的自然溢出就无需加上一个模数了
}
printf("%d\n",ans);
}
return 0;
}

最新文章

  1. Not Hello World
  2. NOR Flash擦写和原理分析
  3. 树形遍历(java)---孩子双亲表示法
  4. 为什么子线程不能做UI操作
  5. [置顶] PHP如何扩展和如何在linux底层对php扩展?
  6. C++ Primer 学习笔记_2_高速入口(继续)
  7. [国嵌攻略][051][NandFlash原理解析]
  8. mysql中使用show table status 查看表信息
  9. MySQL根据出生日期计算年龄的五种方法比较
  10. [多线程] 生产者消费者模型的BOOST实现
  11. 前端开发中使用mac自带apache服务
  12. 20164305 徐广皓 Exp2 后门原理与实践
  13. .NET Core中的路由约束
  14. [LeetCode] Linked List Components 链表组件
  15. WordPress-Word图片上传插件整合教程-Xproer.WordPaster
  16. 查看eclipse版本信息
  17. 如何学php少走弯路
  18. Redis debugging guide---官方
  19. 基础拾遗----RabbitMQ
  20. 『Python基础-15』递归函数 Recursion Function

热门文章

  1. Appium获取toast消息
  2. C++ new 和 delete
  3. JavaWeb_(Mybatis框架)输入和输出参数_五
  4. PHP 之验证码类封装
  5. CentOS6.8安装Docker
  6. git如何将一个远程仓库的某个分支拉取到当前分支?
  7. 【python】详解事件驱动event实现
  8. easy-mock 本地部署
  9. ansible安装、配置ssh、hosts、测试连接
  10. Android之FrameWork