题意 : 给你一个长度为N的字符串 有M个操作 每个操作有两种选择 一种是询问A到B这个区间长度的字符串是否为回文串 另一种是修改位置为A的字符
解题思路:涉及到区间询问 和 点修改 很容易想到最基本的线段树去操作 只是构建有点难想 可以用多项式哈希解决 假设我现在有一个长度为5的字符串abcde
那么它的多项式哈希为 ax + bx^2 + cx^3 + dx^4 + ex^5 这边的abcde的值可以默认成0 ~ 25 x理论可取任意值 这里避免重复 可以取 25以上的值 那么我们可以在
一开始构建两棵线段树 一棵存顺序 一棵存逆序 然后询问的时候只要判断顺序的哈希值和逆序的哈希值是否相同就可以了 当然这边询问到结果后还需处理一下
因为两次的询问可能相差x^?次方 所以要把x^?乘上 比如说我现在abcde的逆序为 edcba 那么我如果询问1 3 顺序的哈希值为 ax + bx^2 + cx^3 逆序哈希值为
cx^3 + bx^4 +ax^5 所以我要给顺序的哈希值乘上x^2才能去判断 一开始取x的时候觉得取什么值都会溢出 其实这边溢出不溢出是没什么关系的。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<list>
#include<stack>
#include<vector>
#include<math.h>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
#define CLR(a, b) memset(a, b, sizeof(a))
#define INF 0x3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100005;
ll sum[2][maxn<<2];
char s[maxn];
ll h[maxn];
void init(){
h[0] = 1;
for(int i = 1;i < maxn;i++)
h[i] = h[i - 1] * 33;
}
void pushup(int rt ,int sign){
sum[sign][rt] = sum[sign][rt<<1] + sum[sign][rt<<1|1];
}
void build(int l ,int r ,int rt,int sign){
if(l == r){
sum[sign][rt] = (s[l - 1] - 'a') * h[l];
return;
}
int m = (l + r) >> 1;
build(lson,sign);
build(rson,sign);
pushup(rt,sign);
}
void update(int pos,char val,int l,int r,int rt,int sign){
if(l == r) {
sum[sign][rt] = (val - 'a') * h[l];
return;
}
int m = (l + r) >> 1;
if(pos <= m) update(pos,val,lson,sign);
else update(pos,val,rson,sign);
pushup(rt,sign);
}
ll query(int L,int R,int l ,int r, int rt,int sign){
if(L <= l && R>= r) return sum[sign][rt];
int m = (l + r) >> 1;
ll ans = 0;
if(L <= m) ans += query(L,R,lson,sign);
if(R > m) ans += query(L,R,rson,sign);
return ans;
}
int main(){
init();
while(scanf("%s",s) != EOF){
int n = strlen(s);
build(1,n,1,0);
reverse(s, s + n);
build(1,n,1,1);
int m;
scanf("%d",&m);
while(m--){
char choose[30];
scanf("%s",choose);
if(choose[0] == 'p'){
int a,b;
scanf("%d%d",&a,&b);
ll ans1 = query(a,b,1,n,1,0);
ll ans2 = query(n - b + 1,n - a + 1,1,n,1,1);
int len = (n - b + 1) - a;
if(len > (b - a + 1)) len = b - a + 1;
if(len > 0){
ans1 *= h[len];
}
else{
len = abs((n - b + 1) - a);
if(len > (b - a + 1)) len = b - a + 1;
if(len > 0){
ans2 *= h[len];
}
}
if(ans1 == ans2) puts("Yes");
else puts("No");
}
else if(choose[0] == 'c'){
int pos;
char val;
scanf("%d %c",&pos,&val);
update(pos,val,1,n,1,0);
update(n - pos + 1,val,1,n,1,1);
}
}
}
return 0;
}