[JZOJ5897]密匙--哈希骚操作

题目链接

太懒了自行Google

分析

这题看了样例解释才知道什么意思

本以为自己身为mo法师蛤希已经掌握的差不多,做了这道题才发现我还是Too Young Too Simple

考虑字符集只有\({a,b}\)怎么做,我们每次二分同时判断要不要转化就好了

std就很强了,我们对每一个字母ch,都对\(S\)串跑遍01蛤希(瞎编的名字)

\(ha[i][ch-'a']=ha[i-1][ch-'a']*w+[s[i]==ch]\)

同时再对\(T\)串跑一遍正常的蛤希,\(ha_t[i]=ha_t[i-1]*w + t[i]\)

这时候我们还是进行二分/倍增求LCP,但怎么判断\(S\)串一个前缀能不能得到\(T\)串对应前缀呢

我们先用\(set\)预处理一下,也就是在对应字符那里插入它在\(S\)中出现的位置,这样我们就能较快的求出一个区间内某个字符出现的位置

考虑这时候我们在判断\(S\)从\(st\)开始的前缀中\([st,st+len]\)部分能否转化为\(T\)串对应部分

我们还是遍历每一个字母,找到在这个区间内出现的一个位置\(pos\)(如果没有就不管),再判断是否需要映射成\(T\)串对应位置的字符,如果需要而且它之前没有被占用(也就是之前没有出现在字母对中),那就对\(T[pos]\)和\(S[pos]\)建立映射关系

同时我们求出这个区间内\(S\)串关于字母\(S[pos]\)的哈希值(如果不知道怎么求的先去学一下\(Rabin-Karp Hash\)),乘上\(T[pos]\)

用一个数\(sum\)累加所有出现字母的这种乘积哈希值,如果没有出现映射矛盾的话,我们会发现如果可以转化成\(T\)串一个前缀,那么这个\(sum\)是会等于\(T\)串对应前缀的哈希值,这是因为\(S\)对应字母的哈希值只有01表示有没有出现,乘上字母的ASIIC值就是该字母在这个区间内的哈希值

代码

/*
code by RyeCatcher
*/
inline char gc(){
static char buf[SIZE],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while((c=gc())>'9'||c<'0')ne=c=='-';x=c-48;
while((c=gc())>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
}
const int maxn=100005;
const int inf=0x7fffffff;
ull ha[maxn][28],hat[maxn],mi[maxn];
set <int> pos[28];
int n,m;
int vis[28];
char s[maxn],t[maxn];
bool chk(int l,int r){
ull tmp=0;
set<int>::iterator it;
int x,y;
memset(vis,-1,sizeof(vis));
for(ri i=0;i<26;i++){
it=pos[i].lower_bound(l);
if(it==pos[i].end()||*it>r)continue;
x=*it,y=t[x-l+1]-'a';
if(vis[i]!=-1||vis[y]!=-1){//判断映射是否矛盾
if(vis[y]!=i||vis[i]!=y){
return 0;
}
}
vis[i]=y,vis[y]=i;
tmp+=(ha[r][i]-ha[l-1][i]*mi[r-l+1])*t[x-l+1];//取出字母的区间哈希值
}
if(tmp==hat[r-l+1])return 1;
return 0;
}
int main(){
FO(key);
read(n),read(m);
scanf("%s",s+1);
scanf("%s",t+1);
for(ri k=0;k<26;k++){
ull tmp=0;
char o='a'+k;
for(ri i=1;i<=n;i++){
if(s[i]!=o)tmp=tmp*31;
else tmp=tmp*31+1;
ha[i][k]=tmp;
}
}
mi[0]=1;
for(ri i=1;i<=n;i++)pos[s[i]-'a'].insert(i),mi[i]=mi[i-1]*31;//预处理
for(ri i=1;i<=m;i++){
hat[i]=hat[i-1]*31+t[i];
}
for(ri o=1;o<=n;o++){
int k=0,p=1;
while(p){
if(o+k+p<=n&&chk(o,o+k+p))k+=p,p=p<<1;
else p=p>>1;
while(o+k+p>n||k+p>m)p=p>>1;
}
printf("%d\n",1+k);
}
return 0;
}

[JZOJ5897]密匙--哈希骚操作的更多相关文章

  1. ssh密匙互信操作【原创】

    1.简便ssh密匙信任方法 只在一台服务器上创建ssh-keygen [root@SMSJKSRVBJ02 ~]# ssh-keygen Generating public/private rsa k ...

  2. 如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

    0x01 问题提出 还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天我要给大家分享的是如 ...

  3. 实现liunx之间无密码访问——ssh密匙

    环境描述 两台linux服务器 172.16.1.22[client],172.16.1.33[server],想要实现client服务器ssh无密码访问server服务器. 使用技术 linux 的 ...

  4. Git科普文,Git基本原理&各种骚操作

    Git简单介绍 Git是一个分布式版本控制软件,最初由Linus Torvalds创作,于2005年以GPL发布.最初目的是为更好地管理Linux内核开发而设计. Git工作流程以及各个区域 Work ...

  5. Ubu18远程登录密匙设置

    Ubu18设置远程密匙登录 相关文件 /etc/ssh/sshd_config 注意vscode使用博客园插件需要进行端口转发,在vscode端口处设置41385 本地生成密匙,任选一种,这里只介绍第 ...

  6. 多节点ssh免密匙登录

    1,在所有节点上,使用yourname用户名执行: ssh-keygen -t dsa -P '' -f /home/yourname/.ssh/id_dsa 2,在node1的/home/yourn ...

  7. SQLServer2008R2企业版密匙

    SQLServer2008R2企业版密匙:  R88PF-GMCFT-KM2KR-4R7GB-43K4B 

  8. visual studio无法输入密匙解决方法

    控制面板->程序和功能->修复/卸载(更改),当到输入密匙界面运行程序,即可出现密匙输入框. 所用程序网上搜索:CrackVS2008ForWindows7

  9. Linux学习(四)单用户模式、救援模式、虚拟机克隆、linux互连(包括密匙登录)

    一.单用户模式 忘记root密码后,找回密码有两种方法: 单用户(grub没有加密的情况下可以使用) 救援模式 这一节我们先讲单用户模式   1.先重启(3种方法) reboot init 6 sho ...

随机推荐

  1. IntelliJ IDEA中构建spring-boot项目

    1. 打开 IDEA ,新建项目 2. 选择Spring Initializr 并在 Choose Initializr Service URL 填入 https://start.spring.io ...

  2. 【转载】 迁移学习简介(tranfer learning)

    原文地址: https://blog.csdn.net/qq_33414271/article/details/78756366 土豆洋芋山药蛋 --------------------------- ...

  3. 26Flutter 日期 和时间戳/格式化日期库/flutter异步/ 官方自带日期组件showDatePicker、时间组件showTimePicker以及国际化

    /* 一.Flutter日期和时间戳 日期转换成时间戳 var now=newDateTime.now(); print(now.millisecondsSinceEpoch); //单位毫秒,13位 ...

  4. (四)UML之顺序图(时序图)

    一.概念 顺序图是交互图的一种形式,它显示对象沿生命线发展,对象之间随时间的交互表示为从源生命线指向目标生命线的消息.顺序图能很好地显示那些对象与其它那些对象通信,什么消息触发了这些通信,顺序图不能很 ...

  5. (十四)Centos之安装vsftp服务

    一.为什么要安装vsftp服务 我们需要向centos操作系统的服务器上上传文件或者下载文件,这时候,ftp有必要安装下,我们选择主流的vsftp 二.安装 第一步:安装vsftp yum insta ...

  6. Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的实现(转)

    MySQL使用load data local infile 从文件中导入数据比insert语句要快,MySQL文档上说要快20倍左右.但是这个方法有个缺点,就是导入数据之前,必须要有文件,也就是说从文 ...

  7. mysql使用truncate截断带有外键的表时报错--解决方案

    报错内容如:1701 - Cannot truncate a table referenced in a foreign key constraint 一.为什么要使用truncate 使用trunc ...

  8. PostgreSQL学习笔记——内置函数

    算术函数(数值计算) +(加).-(减).*(乘)./(除) ABS函数--绝对值: ABS(数值) MOD--求余: MOD(被除数,除数) ROUND--四舍五入: ROUND(对象数值,保留小数 ...

  9. Jupter Notebook常用快捷键与常用的魔法命令

    jupter notebook快捷键整理 Part1 1.删除Cell——双击D 2.撤销删除——Z 3.新建Cell——A/B (向上/向下) 4.命令窗口——P 5.运行——Ctrl+Enter ...

  10. 图形学入门(3)——区域填充算法(region filling)

    继续图形学之旅,我们已经解决了如何画线和画圆的问题,接下来要解决的是,如何往一个区域内填充颜色?对一个像素填充颜色只需调用SetPixel之类的函数就行了,所以这个问题其实就是:如何找到一个区域内的所 ...