题意:给你一个字符串,再给出两种操作,一种是给出一个区间判断这个区间是不是回文串,一种是将字符串的某个字符改成另一个。
思路:一开始看到给出的时间只有500ms就蒙了,然后就去翻了下博客,说一下自己解题过程中遇到的疑惑。
1.这题的哈希多项式公式好奇怪,和之前所做的题的多项式不一样。之前的多项式是字符串的幂次方随着字符串增长而递减的,这题却是递增的。
(这题的公式:h[i]=s[1]+s[2]*p+s[3]*p^2+…..+s[i]*p^(i-1))做完题之后大胆猜测(maybe是方便做线段树的单点更新和区间求和操作?
因为哈希多项式的改变,所以给出两个连续区间的哈希公式,求整个区间的哈希值的公式也要改变。
(加入左边区间的范围是[l,m],右边是[m+1,r],那么整个区间的哈希值是h(l,m)+p^(m-l+1))*h(m+1,r))这个是从左算起的,还有一个从右算起的这里就不写了。
2.还有一个问题是怎么去判断是不是回文串,这里给出了一种很巧妙的方法,就是建立两棵线段树,一棵是按照字符串正向建,另一颗反向建,因此判断是不是回文,只要比较在两棵树中,正向和反向的区间哈希值是不是相等就行了。
思路大致就是如此,下面是ac代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <map>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef unsigned long long ull;
using namespace std;
const int maxn = 1e5 + 5;
const int has = 131;
char str[maxn];
int len, n;
char op[20];
ull sum[2][maxn << 2];
ull p[maxn << 2];
// h[maxn << 2];
void pushup(int rt, int l, int r) {
sum[0][rt] = sum[0][rt << 1] + sum[0][rt << 1 | 1] * p[l];
sum[1][rt] = sum[1][rt << 1] * p[r] + sum[1][rt << 1 | 1] ;
}
void build(int l, int r, int rt) {
if(l == r) {
sum[0][rt] = sum[1][rt] = str[l];
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt, m - l + 1, r - m);
}
void updata(int pos, char a, int l, int r, int rt) {
if(l == r) {
str[pos] = a;
sum[0][rt] = sum[1][rt] = str[pos];
return ;
}
int m = (l + r) >> 1;
if(m >= pos) updata(pos, a, lson);
else updata(pos, a, rson);
pushup(rt, m - l + 1, r - m);
}
ull query(int flag, int L, int R, int l, int r, int rt) {
if(L <= l && R >= r) {
return sum[flag][rt];
}
int m = (l + r) >> 1;
ull ans1 = 0, ans2 = 0, ans = 0, t = 0;
if(L <= m) {//是要对t进行分类讨论的
t += 1;
ans1 = query(flag, L, R, lson);
}
if(R > m) {
t += 2;
ans2 = query(flag, L, R, rson);
}
if(t == 1) ans = ans1;
else if(t == 2) ans = ans2;
else if(t == 3) {
if(flag == 0) {
ans = ans1 + ans2 * p[m - max(l, L) + 1];//这里的max和下面的min是有必要的
} else if(flag == 1) {
ans = ans1 * p[min(R, r) - m] + ans2;
}
}
return ans;
}
int main() {
scanf("%s%d", str + 1, &n);
len = strlen(str + 1);
p[0] = 1;
for(int i = 1; i <= len; i++) p[i] = p[i - 1] * has;
build(1, len, 1);
while(n--) {
int a;
scanf("%s %d", op, &a);
if(op[0] == 'p') {
int b;
scanf("%d", &b);
ull a1 = query(0, a, b, 1, len, 1);
ull a2 = query(1, a, b, 1, len, 1);
if(a1 == a2) printf("Yes\n");
else printf("No\n");
} else if(op[0] == 'c') {
char b;
cin >> b;
updata(a, b, 1, len, 1);
}
}
return 0;
}