http://acm.hdu.edu.cn/showproblem.php?pid=3973

题意

给一个词典和一个主串。有两种操作,查询主串某个区间,问这主串区间中包含多少词典中的词语。修改主串某一位置的字符。

分析

题目要求区间查询,和单点更新,那么最先想到的应该是线段树。可字符串怎么利用线段树呢?用hash!首先将词典按规则hash后放入map,然后将主串的hash值放置入线段树中。问题来了,怎么更新结点的hash值呢?假如现在我们知道了s[l...mid]和s[mid+1...r]的hash值,我需要s[l...r]的hash值,根据我的hash规则(将主串看作是p进制数,左边为高位,p为素数),hash[l...r]=hash[l...mid]*p^(r-mid)+hash[mid+1...r]。另外,被输入卡了好久。。不停RE。需要使用更准确的输入格式,我猜测可能是输入数据之间的空格不定导致的。

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define pd(a) printf("%d\n",a)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define lc idx<<1
#define rc idx<<1|1
#define lson l,mid,lc
#define rson mid+1,r,rc
using namespace std;
typedef long long ll;
template <class T>
void test(T a){cout<<a<<endl;}
template <class T,class T2>
void test(T a,T2 b){cout<<a<<" "<<b<<endl;}
template <class T,class T2,class T3>
void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;}
const int N = 1e6+;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const ll mod = ;
int T;
void testcase(){
printf("Case #%d:\n",++T);
}
const int MAXN = 1e5+;
const int MAXM = ;
const int p = ; struct node{
int l,r;
ll hass;
}tree[MAXN<<];
char str[];
ll P[MAXN];
map<ll,int> ma;
int n;
void init(){
P[]=;
for(int i=;i<MAXN;i++){
P[i]=p*P[i-];
}
}
void Hash(char s[]){
int len = strlen(s);
ll res=;
for(int i=;i<len;i++){
res +=P[len--i]*(s[i]-'a'+);
}
ma[res]=;
}
void push_up(int m,int idx){
tree[idx].hass=tree[lc].hass*P[m]+tree[rc].hass;
}
void build(int l,int r,int idx){
tree[idx].l=l,tree[idx].r=r;
if(l==r){
tree[idx].hass=str[l]-'a'+;
return;
}
int mid = (l+r)>>;
build(lson);
build(rson);
push_up(r-mid,idx);
}
void update(int pos,int idx){
if(tree[idx].l==tree[idx].r){
tree[idx].hass=str[pos]-'a'+;
return;
}
int mid = (tree[idx].l+tree[idx].r)>>;
if(pos<=mid) update(pos,lc);
else update(pos,rc);
push_up(tree[idx].r-mid,idx);
}
ll query(int l,int r,int idx){
if(tree[idx].l>=l&&tree[idx].r<=r)
return tree[idx].hass;
int mid = (tree[idx].l+tree[idx].r)>>;
if(r<=mid) return query(l,r,lc);
else if(l>mid) return query(l,r,rc);
return query(l,mid,lc)*P[r-mid]+query(mid+,r,rc);
} int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int t,m;
scd(t);
init();
T=;
char s1[],s2[];
while(t--){
testcase();
ma.clear();
scd(n);
for(int i=;i<n;i++){
scanf("%s",str);
Hash(str);
}
scanf("%s",str);
int len = strlen(str);
build(,len-,);
scd(m);
while(m--){
scanf("%s",s1);
if(s1[]=='Q'){
int l,r;
scdd(l,r);
if(ma.find(query(l,r,))!=ma.end()) puts("Yes");
else puts("No");
}else{
int pos;
scanf("%d%s",&pos,s2);
str[pos]=s2[];
update(pos,);
}
}
}
return ;
}

HDU - 3973 AC's String(Hash+线段树)的更多相关文章

  1. HDU 3973 AC's String 字符串哈希

    HDU 3973 通过哈希函数将一个字符串转化为一个整数,通过特定的方式可以使得这个哈希值几乎没有冲突(这就是关键之处,几乎没有视为没有= =!, 其实也可以考虑实现哈希冲突时的处理,只是这道题没必要 ...

  2. 题解报告:hdu 1166 敌兵布阵(线段树or树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头 ...

  3. bzoj2124 等差子序列(hash+线段树)

    2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 719  Solved: 261[Submit][Status][Discuss] ...

  4. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  5. HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模

    Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  6. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

  7. HDU 6096 String 排序 + 线段树 + 扫描线

    String Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Problem De ...

  8. HDU 5412——CRB and Queries——————【线段树套Treap(并没有AC)】

    CRB and Queries Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  9. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

随机推荐

  1. linux_shell自定义命令

    一.命令可执行文件所在目录 shell命令可执行文件所在目录是保存在环境变量PATH中的,终端输入如下命令查看 PATH 环境变量的内容: $ echo $PATH 我的linux输出如下: /opt ...

  2. React child

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  3. carson常用linux命令整理

    注:通过日常所用到的一些命令进行整理添加!! 完整的命令可参考:Linux命令大全 1.cp命令 cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录. 2.mount(挂载)命令 在li ...

  4. pycharm5.0 快捷键大全osx

    官网链接https://resources.jetbrains.com/assets/products/pycharm/PyCharm_ReferenceCard_mac.pdf 一直想给别人安利py ...

  5. jquery添加刪除

    創建元素的方法:jquery.javascript/dom,html/text var txt1="<p>Text.</p>";               ...

  6. python之参数解包

    # 参数解包:将整个list当做参数传给函数 list = [1, 2, 4] def add_fn(a, b, c): return a + b + c sum = add_fn(*list) pr ...

  7. codeforces622B

    The Time CodeForces - 622B 给你当前的时间(24小时制):HH:MM.输出 x 分钟后的时间是多少?(24小时制) 不明白可以看看例子哦- Input 第一行给出了当前时间, ...

  8. codeforces706C

    Hard problem CodeForces - 706C 现在有 n 个由小写字母组成的字符串.他想要让这些字符串按字典序排列,但是他不能交换任意两个字符串.他唯一能做的事是翻转字符串. 翻转第  ...

  9. lvs逻辑卷详解

    管理磁盘空间对系统管理员来说是一件重要的日常工作.一旦磁盘空间耗尽就需要进行一系列耗时而又复杂的任务,以提升磁盘分区中可用的磁盘空间.它也需要系统离线才能处理.通常这种任务会涉及到安装一个新的硬盘.引 ...

  10. Hibernate的继承映射

    对象模型示例: 继承映射的实现方式有以下三种: (一)每棵类继承树一张表 (二)每个类一张表 (三)每个子类一张表 (一)每棵类继承树一张表 关系模型如下: 映射文件如下: <hibernate ...