您的位置:首页 > 其它

URAL 1989 Subpalindromes(线段树单点修改+字符串hash)

2015-08-22 17:03 337 查看

题意:

给出一个字符串,长度为10510^5,有m个操作m<=104m<= 10^4。

有两种操作:

1. 询问[l,r][l,r]区间的子串是否回文

2. 将第ii个字符改为cc。

解析:

用字符串哈希+线段树来做这题,线段树用于查询区间的hash值。

建两棵线段树一棵维护从前向后的hash值,另外一棵维护从后向前的hash值。

那么我们判断是否回文串,就只要看正反区间的哈希值之和是否相等就行了。

至于修改就是单点更新了。

mymy codecode

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
typedef unsigned long long ll;
const int N = (int)1e5 + 10;
const int sigma_size = 33;

int n, m;
ll H
;
char str
, str2
;

inline ll idx(char c) { return c - 'a' + 1; }
inline int get(int pos) { return n - pos + 1; }

void init() {
    H[0] = 1;
    for(int i = 1; i < N; i++) {
        H[i] = H[i-1] * sigma_size; 
    }
}

ll lsum[N<<2], rsum[N<<2];
void pushUp(int o, int L, int R) {
    int M = (L + R)/2;
    lsum[o] = H[R - M] * lsum[ls] + lsum[rs];
    rsum[o] = H[R - M] * rsum[ls] + rsum[rs];
}

void build(int o, int L, int R) {
    if(L == R) {
        lsum[o] = idx(str[L]);
        rsum[o] = idx(str2[L]);
        return ;
    }
    int M = (L + R) >> 1;
    build(lson);
    build(rson);
    pushUp(o, L, R);
}

void modify(int o, int L, int R, int pos, int op) {
    if(L == R) {
        if(op == -1) lsum[o] = idx(str[L]);
        else rsum[o] = idx(str2[L]);
        return ;
    }
    int M = (L + R) >> 1;
    if(pos <= M) modify(lson, pos, op);
    else modify(rson, pos, op);
    pushUp(o, L, R);
}

ll query(int o, int L, int R, int ql, int qr, int op) {
    if(ql <= L && R <= qr)
        return (op == -1) ? lsum[o] : rsum[o];
    int M = (L + R) >> 1;
    if(qr <= M) return query(lson, ql, qr, op);
    else if(ql > M) return query(rson, ql, qr, op);
    return query(lson, ql, M, op) * H[qr - M] + query(rson, M+1, qr, op);
}

int main() {
    char oper[20], c[5];
    int a, b;

    init();
    while(~scanf("%s", str+1)) {
        n = strlen(str+1);
        strcpy(str2+1, str+1);
        reverse(str2+1, str2+1+n);

        build(1, 1, n); 
        scanf("%d", &m);

        ll pre, suf;
        while(m--) {
            scanf("%s", oper);
            if(oper[0] == 'p') {
                scanf("%d%d", &a, &b);
                int mid = (a + b) >> 1;
                int flag = (a + b) & 1;
                pre = query(1, 1, n, a, mid, -1);
                suf = query(1, 1, n, get(b), get(mid+flag), 1);
                puts((pre == suf) ? "Yes" : "No");
            }else {
                scanf("%d%s", &a, c);
                str[a] = c[0];
                modify(1, 1, n, a, -1);

                str2[get(a)] = c[0];
                modify(1, 1, n, get(a), 1);
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: