【字符串哈希】URAL1989 Subpalindromes

题意:给定一个字符串,(小于1e5), 有两种操作.
1. 将字符串某一位改成另一个字符。
2. 判断l,r区间内的字符串是不是回文串。

思路:因为字符串不停在变化,即使不变,求出每个子段是否回文也要n方。所以将这个字符串看作正反两个26进制的数,如果某一段是回文的,那他在正反两段中的哈希值应该相等。用树状数组区间求和。另外,由于正反串在源串中位置不同,要乘上到串末端距离,消除误差。

哈希看似很傻很暴力,写起来要注意的地方不少,需要很多巧妙的写法。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
typedef unsigned long long LL;

char t[maxn];
LL hsh[maxn];
LL tree[2][maxn];

void add(int poi,LL d,bool fg) {
    while(poi<maxn) {
        tree[fg][poi]+=d;
        poi+=poi&-poi;
    }
}

LL sum(int poi,bool fg) {
    LL res = 0;
    while(poi) {
        res+=tree[fg][poi];
        poi-=poi&-poi;
    }
    return res;
}

int lt = 0,q=0;

int main() {
    hsh[0] = 1;
    for(int i=1;i<maxn;i++) hsh[i] = hsh[i-1]*27;
    while(~scanf("%s",t)){
        lt = strlen(t);
        memset(tree,0,sizeof(tree));
        for(int i=0;i<lt;i++) {
            add(i+1,(t[i]-'a')*hsh[i],0);
            add(i+1,(t[lt-i-1]-'a')*hsh[i],1);
            //cout<<sum(i+1,1)<<endl;
        }

        scanf("%d",&q);
        while(q--) {
            //cout<<t+1<<endl;
            char ch[22];
            scanf("%s",ch);
            if(ch[0] == 'p') {
                int l,r;
                scanf("%d%d",&l,&r);
                LL sum1 = hsh[lt-r]*(sum(r,0)-sum(l-1,0));
                LL sum2 = hsh[l-1]*(sum(lt-l+1,1)-sum(lt-r,1));
                //cout<<sum1<<" "<<sum2<<endl;
                if(sum1 == sum2) puts("Yes");
                else puts("No");
            }
            else {
                int p;char chh[2];
                scanf("%d%s",&p,chh);
                int x = chh[0]-t[p-1];
                add(p,x*hsh[p-1],0);
                add(lt-p+1,x*hsh[lt-p],1);
                t[p-1] = chh[0];
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值