原题连接:http://blog.csdn.net/zearot/article/details/38921403
题目大意:给定一个字符串,然后有两个操作:
一为修改这个字符串中的任意一个字符,
二为选择其中一个子串,从j到k,判断str[j.....k]这个子串是不是回文串。
题解:这道不能直接用暴力判断子串是不是回文,这样会超时的,要用线段树和多项式哈希字符串来维护。
对于任意一个字符串,可以定义它的哈希值,因此可以从左边开始也可以从右边开始。对于从l到r的一段字符串,有
hashl = str[l] + str[l+1]*k + str[l+2]*k^2 + str[l+3]*k^3 + ……+str[r]*k^(r-l)
hashr = str[r] + str[r+1]*k + str[r+2]*k^2 + str[r+3]*k^3 + ……+str[l]*k^(r-l)
对于这个从l到r的字符串,只要有hashl == hashr,则该字符串为回文串,故只要用线段树维护hashl和hashr便可。
代码如下:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100000+100;
int M,len;
char str[maxn];
int pp[maxn];
struct node{
int hashl,hashr;
}p[maxn<<2];
void PushUp(int ll, int rr, int rt){ //ll表示节点左子树区间个数,rr表示右子树区间个数,rt表示当前节点编号
p[rt].hashl = p[rt<<1].hashl + p[rt<<1|1].hashl*pp[ll];
p[rt].hashr = p[rt<<1].hashr*pp[rr] + p[rt<<1|1].hashr;
}
//Build函数建树
void Build(int l,int r,int rt){ //l,r表示当前节点区间,rt表示当前节点编号
if(l==r) {//若到达叶节点
p[rt].hashl = p[rt].hashr = str[l];
return;
}
int m=(l+r)>>1;
//左右递归
Build(l,m,rt<<1);
Build(m+1,r,rt<<1|1);
//更新信息
PushUp(m-l+1, r-m, rt);
}
void Update(int L,char C,int l,int r,int rt){//l,r表示当前节点区间,rt表示当前节点编号
if(l==r){//到叶节点,修改
p[rt].hashl = p[rt].hashr = C;
return;
}
int m=(l+r)>>1;
//根据条件判断往左子树调用还是往右
if(L <= m) Update(L,C,l,m,rt<<1);
if(L > m) Update(L,C,m+1,r,rt<<1|1);
PushUp(m-l+1, r-m, rt);//子节点更新了,所以本节点也需要更新信息
}
node Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号
if(L <= l && r <= R){
//在区间内,直接返回
return p[rt];
}
int m=(l+r)>>1;
node ANS,ANS1,ANS2;
int flag1 = 0, flag2 = 0;
if(L <= m) ANS1 = Query(L,R,l,m,rt<<1), flag1 = 1;
if(R > m) ANS2 = Query(L,R,m+1,r,rt<<1|1), flag2 = 1;
if(flag1 && !flag2) ANS = ANS1;
else if(!flag1 && flag2) ANS = ANS2;
else if(flag1 && flag2) {
ANS.hashl = ANS1.hashl + ANS2.hashl*pp[m - max(L,l) + 1];
ANS.hashr = ANS1.hashr*pp[min(r,R) - m] + ANS2.hashr;
}
return ANS;
}
int main(){
scanf("%s",str+1);
str[0]='0'; pp[0]=1;
len = strlen(str)-1;
memset(p,0,sizeof(p));
for(int i=1;i<=len;i++){
pp[i] = pp[i-1] * 137;
}
scanf("%d",&M);
Build(1, len, 1);
for(int i=1;i<=M;i++){
char s[25];
scanf("%s",s);
if(s[0] == 'c'){
int a; char b;
scanf("%d %c",&a,&b);
Update(a, b, 1, len, 1);
}
else {
int a, b;
scanf("%d%d",&a,&b);
node ans = Query(a, b, 1, len, 1);
if(ans.hashl == ans.hashr) printf("Yes\n");
else printf("No\n");
}
}
}