hdu3973 AC's String 线段树+字符串hash
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3973/
题意是:给出一个模式串,再给出一些串组成一个集合,操作分为两种,一种是替换模式串中的一个字符,还有一种是查询模式串中[l,r]区间的字符串有没有出现在字符串集合中。
由于数据量很大,只能用O(nlogn)复杂度的算法才能通过,我们首先想到区间查询的操作线段树是可以做的,但是怎么样将一个子串唯一化呢?这就要说道字符串哈希了,我的做法是通过字符串哈希将字符串变成31进制数并且让它自然溢出,也就是对2^64取模。然后我们想到如何合并左右子区间呢?根据哈希的思想我们很容易想到:如果右区间的hash值为hash1,左区间的hash值为hash2,右区间的长度是len,则合并之后的hash=hash2*31^len+hash1,根据这样的策略可以知道任何区间的子串的hash值。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef unsigned long long ull;
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a))
#define prime1 1e9+7
#define prime2 1e9+9
#define pi 3.14159265
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define scand(x) scanf("%llf",&x)
#define f(i,a,b) for(int i=a;i<=b;i++)
#define scan(a) scanf("%d",&a)
#define dbg(args) cout<<#args<<":"<<args<<endl;
#define pb(i) push_back(i)
#define ppb(x) pop_back(x)
#define inf 0x3f3f3f3f
#define maxn 100010
#define maxm 2000005
int n,m,x,y;
ll pp=;
ll t[maxn<<],p[maxm];
char s[maxm],a[maxm];
void init()
{
p[]=;
f(i,,maxm-)
{
p[i]=p[i-]*pp;
}
}
ll gethash(char* s)//获取字符串的哈希值
{
ll ans=;
f(i,,strlen(s)-)
{
ans=ans*pp+s[i]-'a'+;//哈希值自然溢出,也就是对2^64取模
}
return ans;
}
void pushup(int rt,int len)//传入根节点以及右子区间的长度
{
t[rt]=t[rt<<]*p[len]+t[rt<<|];
}
void build(int l,int r,int rt)
{
if(l==r)
{
t[rt]=a[l]-'a'+;
return;
}
int mid=l+r>>;
build(lson);
build(rson);
pushup(rt,r-mid);
}
void update(int l,int r,int rt,int pos,char C)
{
if(l==r)
{
t[rt]=C-'a'+;
return;
}
int mid=l+r>>;
if(pos<=mid)update(lson,pos,C);
else update(rson,pos,C);
pushup(rt,r-mid);
}
ll query(int l,int r,int rt,int L,int R)
{
if(l>=L&&r<=R)//只有区间完全重合的时候取出hash值时不需要另加操作
{
return t[rt];
}
int mid=l+r>>;
if(R<=mid) return query(lson,L,R);//分成三种情况,因为合并的时候需要乘系数
else if(L>mid) return query(rson,L,R);
return query(lson,L,mid)*p[R-mid]+query(rson,mid+,R);
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
std::ios::sync_with_stdio(false);
int tt;
scan(tt);
init();
f(kk,,tt)
{
set<ll> map;//字符串到hash值的映射表
scan(n);
f(i,,n)
{
scanf("%s",s);
map.insert(gethash(s));
}
scanf("%s",a+);
int len=strlen(a+);
build(,len,);
scan(m);
char q[];
pf("Case #%d:\n",kk);
while(m--)
{ scanf(" %s",q);
if(q[]=='Q')
{
scan(x);
scan(y);
x++;//注意代码中线段树的左端点是从1开始的
y++;
// dbg(query(1,len,1,x,y));
if(map.find(query(,len,,x,y))!=map.end())
pf("Yes\n");
else pf("No\n");
}
else if(q[]=='C')
{
char str[];
scan(x);
x++;
scanf("%s",str);
update(,len,,x,str[]);
}
}
}
}
hdu3973 AC's String 线段树+字符串hash的更多相关文章
- 线段树 + 字符串Hash - Codeforces 580E Kefa and Watch
Kefa and Watch Problem's Link Mean: 给你一个长度为n的字符串s,有两种操作: 1 L R C : 把s[l,r]全部变为c; 2 L R d : 询问s[l,r]是 ...
- HDU 3973 线段树+字符串hash
题目大意: 不断修改字符串中的字母,然后询问区间字符串是否处于已给定的字符串集合中 这里将原来的字符串集合保存到hash表中,当然用map,set都没有问题 修改查询都用线段树实现,自己的query函 ...
- cf213E 线段树维护hash
链接 https://codeforces.com/contest/213/problem/E 题目大意 给出两个排列a.b,长度分别为n.m,你需要计算有多少个x,使 得\(a_1 + x; a_2 ...
- MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值
F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...
- BZOJ 2124: 等差子序列 线段树维护hash
2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...
- (线段树 && 字符串的处理)codeforces -- 570C
链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87813#problem/J Description Daniel has a s ...
- 考试题string——线段树。
string[题目描述]给定一个由小写字母组成的字符串 s.有 m 次操作,每次操作给定 3 个参数 l,r,x.如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序 ...
- string [线段树优化桶排]
题意大概是给你一个字符串,1e5次修改,每次给一个区间升序排列或降序排列,最后输出这个字符串; 其实是个挺裸的线段树优化题;但是我没有意识去结合桶排,扑该..... 首先 1.40分算法 O(NMlo ...
- hdu 1828 Picture(线段树 || 普通hash标记)
http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others) Mem ...
随机推荐
- react-router简单使用方法
使用 传值 非Link跳转 路由返回 v2,v3里的跳转,返回和传值 问题 react-router版本 v4.x 跟着官网 https://reacttraining.com/react-route ...
- android framework 之JNI
Java Native Interface ( JN I)是Java本地接口,所谓的本地(native) —般是指C/C++ ( 以下统称C)语言.当使用Java进行程序设计时,一般主要有三种情况需要 ...
- 记php封装app 广告植入问题
<meta http-equiv="X-Frame-Options" content="DENY"> <script type="t ...
- numpy.random模块用法总结
from numpy import random numpy.random.uniform(low=0.0, high=1.0, size=None) 生出size个符合均分布的浮点数,取值范围为[l ...
- Cenots 7 安装mysql cluster 通过rpm 包
环境:Cenots 7 MG:192.168.0.105 NDB:192.168.0.108 NDB:192.168.0.109 SQL:192.168.0.111 SQL:192.168.0.107 ...
- 先搞清楚这些问题,简历上再写你熟悉Java!
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 系列文章介绍 本文是<五分钟学Java>系列文章的一篇 本系列文章主要围绕Java程序员必须掌握的核心技能,结合我个人三年 ...
- Flex布局做出自适应页面--语法和案例
本文发布在: github项目地址:https://github.com/tenadolanter/flex-layout-demo SegmentFault地址:https://segmentfau ...
- 基础JavaScript练习(三)总结
任务目的 实践JavaScript数组.字符串相关操作 任务描述 基于任务四进行升级 将新元素输入框从input改为textarea 允许一次批量输入多个内容,格式可以为数字.中文.英文等,可以通过用 ...
- Ansible-安装配置
主机规划 主机名称 操作系统版本 内网IP 外网IP(模拟) 安装软件 ansi-manager CentOS7.5 172.16.1.180 10.0.0.180 ansible ansi-hapr ...
- Redis系列六 - 浅谈如何设计秒杀系统
前言 设计一个系统之前,我们肯定要先确认系统业务场景是怎样的,下面就以某电商平台上的秒杀活动为场景,一起来探讨一个秒杀系统改如何去设计. 场景 我们现在要卖100件纸尿布,按照系统的用户量及以往经验来 ...