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. Setting Tomcat Heap Size (JVM Heap) in Eclipse

    this article picked from:http://viralpatel.net/blogs/setting-tomcat-heap-size-jvm-heap-eclipse/ Rece ...

  2. 数据驱动测试之—— Excel+TestNG

    对于利用Webdriver做自动化的童鞋,对于如何将元素或者输入数据如何和编码分离都应该不会太陌生,本着一边学习一边分享的心态,大概总结了一下关于利用CSV.XML以及Excel来存放数据,然后在结合 ...

  3. Jmeter While Controller 使用${__jexl2(,)}

    1. String [] str ={"1","2","3"}; vars.putObject("strArray",s ...

  4. 浏览器的F5和Ctrl+F5

    在浏览器里中,按F5键和按F5同时按住Ctrl键(简称Ctrl+F5),效果是不同,到底两者有什么区别呢? 假如我第一次访问过http://localhost/home,这个网页是个动态网页,每次访问 ...

  5. Jfrog Artifactory 创建docker 镜像仓库以及 push 镜像到 该仓库.

    1. 安装aitifactory 以及 启动 使用30天有效期激活 不在阐述. 2. 登录artifactory username:admin password:password 3. 创建 仓库 在 ...

  6. Angular @的作用

    <!DOCTYPE html><html lang="zh-cn" ng-app="myApp"><head> <me ...

  7. TMainMenu - 隐藏与显示菜单

    //隐藏与显示菜单 Self.Menu := nil; {隐藏菜单} Self.Menu := MainMenu1; {显示菜单}

  8. C# region指令和控制台清零

    region指令 有的时候,为了完成一个需求,可能会写几十行.几百行.甚至几千行代码. 当代码数量非常多的时候,尽管你可以使用很详细的注释来帮助阅读,但也不太容易分清楚哪些代码在干什么事情. 因此,C ...

  9. VMware配置Linux虚拟机访问外网

    [虚拟机版本] 系统版本 : Centos 6.8 [连接方法] 网络模式:桥接模式 ps:本人比较喜欢用桥接,直接NAT也是可以的 [配置步骤] 1.配置网卡 #配置命令 vi /etc/sysco ...

  10. Chinese Postman Problem Aizu - DPL_2_B(无向图中国邮路问题)

    题意: 带权无向图上的中国邮路问题:一名邮递员需要经过每条边至少一次,最后回到出发点,一条边多次经过权值要累加,问最小总权值是多少.(2 <= N <= 15, 1 <= M < ...