這題困擾了我一天,在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;
}