题面

对于一个字符集大小为C的字符串P,我们可以将任意两种字符在P中的位置进行互换,例如P=abcba,我们交换a,b就变为bacab,交换a,d就变为dbcbd,交换可以进行任意次。若交换后P变为了字符串Q,则我们称Q与P是匹配的。

现在给定两个字符集大小为C的字符串S,T,请你求出S中有多少个连续子串与T是匹配的。

100%的数据:1 <= n,m,C <= 10^6 , Case = 3

100

考虑哈希,

我们给一个长度为m的序列,规定它的哈希值为:\(\sum_{c \belong C}hh^{fi_c}*\sum_{T_i=c}HH^{i-fi_c}\)

那么维护这个哈希值就好了。

Code

#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
const int inf=0x7fffffff;
const char* fin="string.in";
const char* fout="string.out";
const int maxn=1000007;
const ll mo=1000000007ll;
int t,C,n,m,ans,a[maxn],fi[maxn],en[maxn],ne[maxn];
int dans[maxn];
ll h,H,hh[maxn],HH[maxn],nh[maxn],nH[maxn],_h[maxn],_H[maxn],_fi[maxn];
int read(){
int x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
ll qpower(ll a,ll b){
ll c=1;
while (b){
if (b&1) c=c*a%mo;
a=a*a%mo;
b>>=1;
}
return c;
}
ll ni(ll v){return qpower(v,mo-2);}
void update(int de,int now){
if (_fi[de]<now){
int tmp=now-_fi[de];
_h[de]=_h[de]*nh[tmp]%mo;
_H[de]=_H[de]*nh[tmp]%mo;
_fi[de]=now;
}
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d",&t,&C);
hh[0]=HH[0]=nh[0]=nH[0]=1;
ll hhh=ni(797ll),HHH=ni(648567ll);
fo(i,1,maxn-1){
hh[i]=797ll*hh[i-1]%mo,HH[i]=648567ll*HH[i-1]%mo;
nh[i]=hhh*nh[i-1]%mo,nH[i]=HHH*nH[i-1]%mo;
}
while (t--){
scanf("%d%d",&n,&m);
fo(i,1,n) a[i]=read();
h=H=0;
memset(fi,0,sizeof fi);
fo(i,1,m){
int j=read();
if (!fi[j]) H=(H+hh[fi[j]=i])%mo;
else H=(H+hh[fi[j]]*HH[i-fi[j]])%mo;
}
memset(fi,0,sizeof fi);
memset(ne,0,sizeof ne);
//memset(_h,0,sizeof _h);
fo(i,1,m){
int j=a[i];
if (!fi[j]){
h=(h+hh[fi[j]=en[j]=i])%mo;
_h[j]=_H[j]=hh[i];
_fi[j]=1;
}else{
ne[en[j]]=i;
en[j]=i;
h=(h+hh[fi[j]]*HH[i-fi[j]])%mo;
_h[j]=(_h[j]+hh[fi[j]]*HH[i-fi[j]])%mo;
}
}
dans[0]=0;
ans=(H==h);
if (H==h) dans[++dans[0]]=1;
fo(i,m+1,n){
int ad=a[i],de=a[i-m];
h=(h*nh[1])%mo;
//_h[de],_H[de]
update(de,i-m+1);
//
h-=_h[de];
if (ne[fi[de]]){
int tmp=ne[fi[de]]-fi[de];
fi[de]=ne[fi[de]];
_h[de]-=_H[de];
_H[de]=_H[de]*hh[tmp]%mo;
_h[de]=_h[de]*hh[tmp]%mo*nH[tmp]%mo;
}else fi[de]=0,_h[de]=0;
h+=_h[de];
//
if (!fi[ad]){
fi[ad]=en[ad]=i;
h=(h+hh[m])%mo;
_h[ad]=_H[ad]=hh[m];
_fi[ad]=i-m+1;
}else{
ne[en[ad]]=i;
en[ad]=i;
update(ad,i-m+1);
h=(h+_H[ad]*HH[i-fi[ad]])%mo;
_h[ad]=(_h[ad]+_H[ad]*HH[i-fi[ad]])%mo;
}
h=(h%mo+mo)%mo;
ans+=(H==h);
if (H==h) dans[++dans[0]]=i-m+1;
}
printf("%d\n",ans);
fo(i,1,dans[0]) printf("%d ",dans[i]);
printf("\n");
}
return 0;
}

【JZOJ5093】【GDSOI2017第四轮模拟day3】字符串匹配 哈希的更多相关文章

  1. 【JZOJ5094】【GDSOI2017第四轮模拟day3】鸽子 计算几何+floyd

    题面 养鸽人要监视他的鸽子,有n只鸽子站在平面上,他可以在m个给定的点上设置监视器,如果一只鸽子在某个监视器上或者在两个监视器所连直线上或者在三个监视器所连直线的三角形内则其就咕咕咕了,现在养鸽人要让 ...

  2. CCF模拟题 字符串匹配

    字符串匹配 时间限制: 1.0s 内存限制: 256.0MB 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写 ...

  3. 选拔赛 hash 字符串匹配 哈希算法(白书p374)

    hash   Description dr所在国度的有个奇怪的规定:他们的字母不是a~z,而是用1~1000表示. 利用这个奇怪的规定,dr想出了一个好玩的游戏:首先给出n个字符串(当然每个字符用1~ ...

  4. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  5. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

  6. 字符串匹配(hash算法)

    hash函数对大家来说不陌生吧 ? 而这次我们就用hash函数来实现字符串匹配. 首先我们会想一下二进制数. 对于任意一个二进制数,我们将它化为10进制的数的方法如下(以二进制数1101101为例): ...

  7. 【C++实现python字符串函数库】二:字符串匹配函数startswith与endswith

    [C++实现python字符串函数库]字符串匹配函数startswith与endswith 这两个函数用于匹配字符串的开头或末尾,判断是否包含另一个字符串,它们返回bool值.startswith() ...

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

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

  9. C语言字符串匹配函数

    C语言字符串匹配函数,保存有需要时可以用: #include <stdio.h> #include <stdlib.h> #include <string.h> # ...

随机推荐

  1. 07_Spring事务处理

    一.事务概述 数据库的事务: 事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等.事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出 ...

  2. reac-native + typescript 的环境搭建

    一. RN-TS环境搭建 . 安装RN脚手架 yarn add create-react-native-app -g yarn global add typescript . 创建项目文件夹 crea ...

  3. 将ERF格式转换成PCAP格式

    在研究网络流量分析的时候,wireshark默认采用pcap格式.对于用Endace DAG捕捉卡捕获的数据包,一般来说,都是erf格式的.一般来说,此种格式包含了更多了链路层信息.而我们采用wire ...

  4. python print输出format太好用了

    不用担心什么其他的东西了,直接用format: print("{}的Ground,Detected,DetectedRight个数分别为{},{},{},".format(cate ...

  5. osg::BlendFunc来设置透明度

    osg::BlendFunc介绍 混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果.      假设我们需要 ...

  6. 2019-6-14-WPF-shows-that-some-windows-in-multithreading-will-be-locked-in-the-PenThreadWorker-constr...

    title author date CreateTime categories WPF shows that some windows in multithreading will be locked ...

  7. [Swoole系列入门教程 3] 心跳检测

    一.Swoole 的4大知识点: 1.TCP/UDP服务器 2.微服务 3.协程 二.同步与异步: 同步买奶茶:小明点单交钱,然后等着拿奶茶: 异步买奶茶:小明点单交钱,店员给小明一个小票,等小明奶茶 ...

  8. 吴恩达《机器学习》课程总结(5)_logistic回归

    Q1分类问题 回归问题的输出可能是很大的数,而在分类问题中,比如二分类,希望输出的值是0或1,如何将回归输出的值转换成分类的输出0,1成为关键.注意logistics回归又称 逻辑回归,但他是分类问题 ...

  9. scrapy中的Request和Response对象

    前言: 如果框架中的组件比做成是人的各个器官的话,那个Request和Response就是血液,Item就是代谢产物 Request对象: 是用来描述一个HTTP请求,其构造参数有 url 请求的UR ...

  10. JasperReports报表数据源10

    数据源的结构数据容器.同时生成报告,Jasper报表引擎获得来自数据源的数据.数据可以从数据库,XML文件,对象数组和集合中的对象来获得.我们将在本章填充报告所看到的fillReportXXX()方法 ...