ural1989(字符串hash+线段树)

来源:互联网 发布:js 自定义日期选择器 编辑:程序博客网 时间:2024/05/16 15:41

这题困扰了我一天,在timus上用G++交总是超时,后来改用visualc++2010就ac了,不知道为什么,求大牛解释。

题意:给一个长度为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[N];char s[N];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;}



0 0
原创粉丝点击