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 ...
随机推荐
- docker运行mysql主从备份,读写分离
1)从Docker官方下拉MySQL的image 打开https://hub.docker.com/ 搜索mysql 在docker中运行 默认tag为latest docker pull mysql ...
- Jupyter自定义设置详解
今天专门花时间总结梳理一下jupyter的一些高级设置,jupyter我已经介绍过一次基本内容了,Setup and Linux | James Chen's Blogs,尤其是如何在服务器运行jup ...
- 没有admin权限如何免安装使用Node和NPM
此教程只针对于在windows系统上没有admin权限和软件安装权限,但是又希望能像安装版一样使用Node和NPM的用户. 步骤一: 下载压缩版node 访问https://nodejs.org/en ...
- install jekyll
最直接的方法就是运行快速指南中的命令: gem install jekyll 这个时候会提示: Command 'gem' not found, but can be installed with: ...
- LSTM 句子相似度分析
使用句子中出现单词的Vector加权平均进行文本相似度分析虽然简单,但也有比较明显的缺点:没有考虑词序且词向量区别不明确.如下面两个句子: "北京的首都是中国"与"中国的 ...
- 自制一个可编辑QueryString的类URLModifier
有些情况下,需要 新增/删除/替换 url中的部分Querystring中的参数,而.net自带的Uri类只能解析,不能编辑,,并且如果是Relative类型的链接,转成Uri类型之后,很多参数又不能 ...
- 启动tomcat报错 Unable to process Jar entry [module-info.class] from Jar...[xxx.xx.jar!\] for annotations
Java Web 项目tomcat启动报错module-info.class 从git 上面拉下的项目,运行报错. jdk.maven配置正常 tomcat启动遇见的问题: Unable to pro ...
- 一文看懂js中元素的客户区大小(clientWidth,clientHeight)
元素的客户区 元素的客户区大小,指的是元素内容及其内边距所占据的空间大小. 相关属性如下: 1. clientWidth:元素内容区宽度+元素左右内边距 2. clientHeight:元素内容区高度 ...
- js中如何判断属性是对象实例中的属性还是原型中的属性
ECMAScript5中的hasOwnProperty()方法,用于判断只在属性存在与对象实例中的时候,返回true,in操作符只要通过对象能访问到属性就返回true. 因此只要in操作符返回true ...
- Vue双向绑定的实现原理系列(三):监听器Observer和订阅者Watcher
监听器Observer和订阅者Watcher 实现简单版Vue的过程,主要实现{{}}.v-model和事件指令的功能 主要分为三个部分 github源码 1.数据监听器Observer,能够对数据对 ...