ural1989(字符串hash+线段树)
2014-10-31 20:55
417 查看
这题困扰了我一天,在timus上用G++交总是超时,后来改用visualc++2010就ac了,不知道为什么,求大牛解释。
题意:给一个长度为n串,两种操作:1、修改一个字符;2、询问区间[l,r]上的字符串是否为回文串。
先介绍一下字符串hash:将某个字符串用一个正整数代替。现假设只有小写字母的串,一个有26个字母,比如aabb,将其转化成0011,然后将其转化成一个26进制的数字。
思路:长度是100000的26进制数,这肯定会溢出,但没关系,我们用unsigned long long 就可以了,让它自动溢出即可。然后某个数字就对应一个字符串,虽然有些不同串对应同一个数字,但是概率非常小,可以忽略不计。从左到右、从右到左进行两次hash,如果是回文串,那么对应的整数必定存在某种关系(可以理解成相等),对于更新操作,就是单点更新。
代码如下:
题意:给一个长度为n串,两种操作:1、修改一个字符;2、询问区间[l,r]上的字符串是否为回文串。
先介绍一下字符串hash:将某个字符串用一个正整数代替。现假设只有小写字母的串,一个有26个字母,比如aabb,将其转化成0011,然后将其转化成一个26进制的数字。
思路:长度是100000的26进制数,这肯定会溢出,但没关系,我们用unsigned long long 就可以了,让它自动溢出即可。然后某个数字就对应一个字符串,虽然有些不同串对应同一个数字,但是概率非常小,可以忽略不计。从左到右、从右到左进行两次hash,如果是回文串,那么对应的整数必定存在某种关系(可以理解成相等),对于更新操作,就是单点更新。
代码如下:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<stdio.h> #include<stdlib.h> #include<math.h> #define N 100005 #define LL unsigned long long #define inf 0x7ffffff #define eps 1e-9 #define pi acos(-1.0) using namespace std; LL f ; char s ; int n; struct node { int l,r; LL suml,sumr;//记录从左到右和从右到左的hash值 }tree[4*N]; void pushup(int o) { tree[o].suml = tree[2*o].suml + tree[2*o+1].suml; tree[o].sumr = tree[2*o].sumr + tree[2*o+1].sumr; } void build(int o,int l,int r) { tree[o].l = l; tree[o].r = r; if(l == r) { tree[o].suml = f[l-1]*(s[l-1] - 'a'); tree[o].sumr = f[n-l]*(s[l-1] - 'a'); return ; } int m = (l+r)/2; build(2*o,l,m); build(2*o+1,m+1,r); pushup(o); } void update(int o,int pos,int num) { if(tree[o].l == tree[o].r){ tree[o].suml = f[ tree[o].l - 1 ]*num; tree[o].sumr = f[ n-tree[o].l ]*num; return ; } int m = (tree[o].l+tree[o].r)/2; if(pos <= m) update(2*o,pos,num); else update(2*o+1,pos,num); pushup(o); } LL suml,sumr; void query(int o,int x,int y) { if(x <= tree[o].l && tree[o].r <= y) { suml += tree[o].suml; sumr += tree[o].sumr; return; } int m = (tree[o].l+tree[o].r)/2; if(m >= x) query(2*o,x,y); if(y > m) query(2*o+1,x,y); } int main() { //freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); int i; f[0] = 1; for(i = 1; i < N; i++) f[i] = f[i-1]*27; while(scanf("%s",s) != EOF) { n = strlen(s); build(1,1,n); int q; scanf("%d",&q); while(q--) { scanf("%s",s); if(s[0] == 'p') { int x,y; scanf("%d%d",&x,&y); suml = sumr = 0; query(1,x,y); int k1 = x-1; int k2 = n-y; if(k1 > k2) sumr *= f[k1-k2];//这里自己举个例子想一下 else suml *= f[k2-k1]; if(suml == sumr) printf("Yes\n"); else printf("No\n"); } else{ int x; scanf("%d%s",&x,s); update(1,x,s[0]-'a'); } } } return 0; }
相关文章推荐
- URAL 1989 Subpalindromes(线段树单点修改+字符串hash)
- URAL - 1989 Subpalindromes——字符串哈希 + 线段树
- URAL 1989 Subpalindromes(字符串HASH&线段树单点更新)
- URAL 1486 Equal Squares 二维字符串Hash + 邻接表分组
- URAL-1989 Subpalindromes 多项式Hash+树状数组
- 1989-字符串分割
- ural1007 Code Words (字符串处理)
- ural 1989(树状数组+多项式hash)
- URAL 1989 Subpalindromes
- URAL - 1989 Subpalindromes hash & 树状数组 | 线段树
- URAL 1989 Subpalindromes 思路
- 字符串专项:Ural 1723
- 【URAL 1989】 Subpalindromes(线段树维护哈希)
- Ural1094 && Ural1038(简单字符串)
- Ural1089(字符串处理)
- 字符串专项:Ural 1102
- URAL 1486(二维字符串hash)
- URAL 1612. Tram Forum(字符串啊 )
- [URAL-1517][求两个字符串的最长公共子串]
- URAL 1989. Subpalindromes