51Nod 算法马拉松28 B题 相似子串 哈希
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - 51Nod1753
题意概括
两个字符串相似定义为:
1.两个字符串长度相等
2.两个字符串对应位置上有且仅有至多一个位置所对应的字符不相同
给定一个字符串,每次询问两个子串在给定的规则下是否相似。给定的规则指每次给出一些等价关系,如‘a'=’b',‘b'=’c'等,注意这里的等价关系具有传递性,即若‘a'=’b',‘b'=’c',则‘a'=’c'。
题解
我们弄一个可以通过前缀求得区间某一个字母的排列的哈希。
然后判断两个字符串是否相等,就是把该区间所有的字母的哈希值整合起来。
具体看代码。
然后就是二分。
如果两个串完全相等,那么YES。
我们二分,取一个mid,对于mid来说:
如果 左串1≠左串2 且 右串1≠右串2,那么可以确定是NO了。
否则 如果 左串1≠左串2,那么继续弄左串,否则继续弄右串。
时间复杂度:N*26*logN ≈ 1e8而且常数较大。
但是时限有5s,所以可以过去。
代码
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const int L=300000+5;
LL p=233333333,mod=1000000007,Inv=474576274;
int n,m,a[L],fa[26];
LL ha[L][26],Pow[L];
char str[L];
int getf(int k){
return fa[k]==k?k:fa[k]=getf(fa[k]);
}
LL gethash(int L,int R){
LL Hash=0;
for (int i=0;i<26;i++){
LL x=(ha[R][i]+mod-ha[L-1][i]*Pow[R-L+1]%mod)%mod;
Hash=(Hash+x*(getf(i)+1))%mod;
}
return Hash;
}
int main(){
scanf("%s",str);
n=strlen(str);
Pow[0]=1;
for (int i=1;i<=n;i++)
Pow[i]=Pow[i-1]*p%mod;
for (int i=1;i<=n;i++)
a[i]=str[i-1]-'a';
// 注意,这里只是对于同一个字母的哈希。最后在汇总的时候,要乘上(字母值+1)防止0的出现。
memset(ha,0,sizeof ha);
for (int i=1;i<=n;i++){
for (int j=0;j<26;j++)
ha[i][j]=ha[i-1][j]*p%mod;
ha[i][a[i]]=(ha[i][a[i]]+1)%mod;
}
scanf("%d",&m);
while (m--){
int k,L1,R1,L2,R2;
scanf("%d%d%d%d%d",&k,&L1,&R1,&L2,&R2);
for (int i=0;i<26;i++)
fa[i]=i;
for (int i=1;i<=k;i++){
char ch[5];
scanf("%s",ch);
fa[getf(ch[0]-'a')]=getf(ch[1]-'a');
}
if (R1-L1+1!=R2-L2+1){
puts("NO");
continue;
}
if (gethash(L1,R1)==gethash(L2,R2)){
puts("YES");
continue;
}
bool flag=1;
int le=1,ri=R1-L1+1,mid;
while (le<ri){
mid=(le+ri)>>1;
LL haL1=gethash(L1+le-1,L1+mid-1);
LL haL2=gethash(L2+le-1,L2+mid-1);
LL haR1=gethash(L1+mid,L1+ri-1);
LL haR2=gethash(L2+mid,L2+ri-1);
if (haL1!=haL2&&haR1!=haR2){
flag=0;
break;
}
if (haL1!=haL2)
ri=mid;
else
le=mid+1;
}
puts(flag?"YES":"NO");
}
return 0;
}
51Nod 算法马拉松28 B题 相似子串 哈希的更多相关文章
- 51Nod 算法马拉松28 C题 栈 单调队列
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - 51Nod1952 题意概括 有一个栈,有3种操作: Ο 从栈顶加入一个元素 Ο 从栈底加入一个元素 Ο 从栈 ...
- 51Nod 算法马拉松28 A题 先序遍历与后序遍历 分治
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - 51Nod1832 题意概括 对于给定的一个二叉树的先序遍历和后序遍历,输出有多少种满足条件的二叉树. 两棵二 ...
- 51NOD 算法马拉松8
题目戳这里:51NOD算法马拉松8 某天晚上kpm在玩OSU!之余让我看一下B题...然后我就被坑进了51Nod... A.还是01串 水题..怎么乱写应该都可以.记个前缀和然后枚举就行了.时间复杂度 ...
- 51nod 算法马拉松 34 Problem D 区间求和2 (FFT加速卷积)
题目链接 51nod 算法马拉松 34 Problem D 在这个题中$2$这个质数比较特殊,所以我们先特判$2$的情况,然后仅考虑大于等于$3$的奇数即可. 首先考虑任意一个点对$(i, j)$ ...
- 随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3
先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率 假 ...
- 51Nod 算法马拉松21(迎新年)
这次打算法马拉松是在星期五的晚上,发挥还算正常(废话,剩下的题都不会= =). 讲讲比赛经过吧. 8:00准时发题,拿到之后第一时间开始读. A配对,看上去像是二分图最大权匹配,一看范围吓傻了,先跳过 ...
- 51Nod 算法马拉松22 开黑记
这是一场惨烈的开黑大战,始于全机房开黑指望刷进rank前十拿钱的壮志,终于被各路神犇怒踩成rank20,差点200点头盾不保的落魄,想起将近一年前ad和zcg等学长挤进rank10的壮举,不由得唏嘘, ...
- 51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛
OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就 ...
- 51Nod 算法马拉松23 开黑记
惨啊……虽然开了半天黑,但是还是被dalao们踩了…… 第二次开黑,还是被卡在rank20了,我好菜啊……= = 写一写比赛经过吧…… 看到题之后习惯性都打开,A~D看上去似乎并没有什么思路,F应该是 ...
随机推荐
- Vue Admin - 基于 Vue & Bulma 后台管理面板
Vue Admin 是一个基于 Vue 2.0 & Bulma 0.3 的后台管理面板(管理系统),相当于是 Vue 版本的 Bootstrap 管理系统,提供了一组通用的后台界面 UI 和组 ...
- spfa判负环
bfs版spfa void spfa(){ queue<int> q; ;i<=n;i++) dis[i]=inf; q.push();dis[]=;vis[]=; while(!q ...
- Netty入门(4) - 附带的ChannelHandler和Codec
使用SSL/TLS创建安全的Netty程序 Java提供了抽象的SslContext和SslEngine,实际上SslContext可以用来获取SslEngine来进行加密和解密.Netty拓展了Ja ...
- Java SE之装箱与拆箱【基本数据类型的包装类/==与equals方法】
对象包装器.自动装箱与拆箱 2016/11/30 晚 特点 1.所有的基本类型都有一个包装器类与之对应.[Integer,Boolean,Long,Character,Shor ...
- Prometheus 监控 Nginx 流量 (三)
介绍 基于Openresty和Prometheus.Consul.Grafana设计的,实现了针对域名和Endpoint级别的流量统计,使用Consul做服务发现.KV存储,Grafana做性能图展示 ...
- C语言中#ifdef,#ifndef和#endif的作用
现在规定一下头文件书写规范, 根据陈皓编写的跟我一起些makefile,一定要记住:头文件中应该只是声明,而定义应该放在C/C++文件中.否则如果出现有定义,比如头文件中有int a =2;如果有多个 ...
- ubuntu16.04+anaconda的安装+解决conda不可用(配置路径)+卸载
首先一点,之前我一直自己安装python,然后直接在python环境下再安装第三方库,但自从另一台电脑重装系统之后,我当时在没有python的情况下直接安装的anaconda,觉得她超级好用(所以如果 ...
- Web前端的缓存机制(那些以代价换来的效率)
对于Web前端而言,cache可以说是无处不在,通常是2个环节之间,就会引入一个cache做为提升整体效率的角色.例如A和B两者之间的数据交换,为了提升整体的效率,引入角色C,而C被用于当做热点数据的 ...
- ubuntu下安装搜狗输入法以及出现不能输入中文的解决办法
1. 官网下载安装包 http://pinyin.sogou.com/linux/?r=pinyin 下载你需要的版本,这里选择64位版. 2. 进入软件中心安装 3. 修改ibus为fcitx im ...
- C语言函数调用栈(二)
5 函数调用约定 创建一个栈帧的最重要步骤是主调函数如何向栈中传递函数参数.主调函数必须精确存储这些参数,以便被调函数能够访问到它们.函数通过选择特定的调用约定,来表明其希望以特定方式接收参数.此外, ...