题目链接: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的更多相关文章

  1. 线段树 + 字符串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]是 ...

  2. HDU 3973 线段树+字符串hash

    题目大意: 不断修改字符串中的字母,然后询问区间字符串是否处于已给定的字符串集合中 这里将原来的字符串集合保存到hash表中,当然用map,set都没有问题 修改查询都用线段树实现,自己的query函 ...

  3. cf213E 线段树维护hash

    链接 https://codeforces.com/contest/213/problem/E 题目大意 给出两个排列a.b,长度分别为n.m,你需要计算有多少个x,使 得\(a_1 + x; a_2 ...

  4. MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思维+线段树维护hash值

    F - Permutation 思路:对于当前的值x, 只需要知道x + k, x - k这两个值是否出现在其左右两侧,又因为每个值只有一个, 所以可以转换成,x+k, x-k在到x所在位置的时候是否 ...

  5. BZOJ 2124: 等差子序列 线段树维护hash

    2124: 等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一 ...

  6. (线段树 && 字符串的处理)codeforces -- 570C

    链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87813#problem/J Description Daniel has a s ...

  7. 考试题string——线段树。

    string[题目描述]给定一个由小写字母组成的字符串 s.有 m 次操作,每次操作给定 3 个参数 l,r,x.如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序 ...

  8. string [线段树优化桶排]

    题意大概是给你一个字符串,1e5次修改,每次给一个区间升序排列或降序排列,最后输出这个字符串; 其实是个挺裸的线段树优化题;但是我没有意识去结合桶排,扑该..... 首先 1.40分算法 O(NMlo ...

  9. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

随机推荐

  1. 探索Kinect的更多可能——亲历第十九届机器人世界杯RoboCup

    作者:微软亚洲研究院资深项目经理 吴国斌 2015年7月19日,第十九届RoboCup机器人世界杯足球赛,在中国合肥隆重开幕.来自全球七十六个国家和地区的一百余支代表队参加了决赛,他们优秀的作品给观众 ...

  2. 【U创营学员招募】8节免费云计算课程,让你轻松掌握生产技能

    课程不错,免费听课.免费听课.免费听课,强烈推荐-! 公众号对话框回复"课程助手" 即可报名! ---END---

  3. 剑指offer-18-2. 删除链表中重复的结点

    剑指offer-18-2. 删除链表中重复的结点 链表 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3-> ...

  4. android 应用程序与服务端交互

    http://www.cnblogs.com/freeliver54/archive/2012/06/13/2547765.html 简述了Service的一些基础知识以及Service和Thread ...

  5. iOS多线程之Thread

    多线程 • Thread 是苹果官方提供的,简单已用,可以直接操作线程对象.不过需要程序员自己管理线程的生命周期,主要是创建那部分 优缺点 面向对象,简单易用 直接操作线程对象 需要自己管理线程生命周 ...

  6. qt creator源码全方面分析(3-1)

    目录 qtcreator.pro 包含qtcreator.pri include(filename) Qt版本判断 message(string) $$运算符 error(string) 包含doc. ...

  7. Nginx 配置GeoIP2 禁止访问,并允许添加白名单过滤访问设置

    配置环境:Centos 7.6 + Tengine 2.3.2 GeoIP2 下载地址:https://dev.maxmind.com/geoip/geoip2/geolite2/ 1. Nginx  ...

  8. sql -- 多表关联,update(用户奖励)

    表设计: users_buy: users_score: 需求: 1.根据用户分组,找出用户消费最高的金额 select user_name, max(paymoney) as pm from use ...

  9. Java和C++引用的区别

    Java的引用实际上是对指针的一个封装. C++的引用是变量的一个别名. Java的定义出来的变量(除了基本类型)其实就是一个引用,指向真正的对象. C++可以通过将引用传入函数,在函数内修改所引用的 ...

  10. Mysql或者SQL Server数据库的运行机制和体系架构

    一.MySQL主要分为以下几个组件: 连接池组件 管理服务和工具组件 SQL接口组件 分析器组件 优化器组件 缓冲组件 插件式存储引擎 物理文件 二.MySql的组成:Mysql是由SQL接口,解析器 ...