【线段树 + 哈希字符串匹配】URAL 1989. Subpalindromes

 URAL 1989. Subpalindromes

  • 题意:对一个字符串有两个操作:(1)查询区间[l, r]子串是不是回文串. (2)修改某个位置上的字符

  • 思路:这个有点显然是线段树,但问题就是我们应该用线段树维护什么?
  1. 我们用线段树维护的当然是两个值:Lval(正串的哈希值),Rval(反串的哈希值)。那么问题又来了,是整个串的哈希值还是区间子串的哈希值呢?
  2. 这里我用的是整个串的哈希值,区间外的“数位”上权值为0.

举个栗子【做题的时候打的草稿,不要嫌弃┭┮﹏┭┮】

 

 但是不知道大家有没有意识到一个问题:


 注意

  • 如果查询区间长度是奇数,那么要去掉中间的那个字符。【这就要求我们长度为1时要特判为Yes】
  • 建树时,字符串是[0, n - 1],但是线段树是[1, n],不要写飘了【其实是我自己写飘了www】
  • 还有就是结构体'+'重载,返回类型是node.  qwq
  • END

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define MID (r + l) >> 1
#define lsn rt << 1
#define rsn rt << 1 | 1
#define Lson lsn, l, mid
#define Rson rsn, mid + 1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 7;
const ull base = 233;
ull p[maxN];
char ans[2][10], s[maxN];
int n, m;
void init()
{
    strcpy(ans[0], "No");
    strcpy(ans[1], "Yes");
    p[0] = 1;
    for(int i = 1; i <= n; i ++ )
        p[i] = p[i - 1] * base;
}
struct node{
    ull Lval, Rval;
    node() {}
    node(ull a, ull b) : Lval(a), Rval(b) {}
    friend node operator + (node n1, node n2) { return node(n1.Lval + n2.Lval, n1.Rval + n2.Rval); }
}tree[maxN << 2];
void pushup(int rt) { tree[rt] = tree[lsn] + tree[rsn]; }
void build_tree(int rt, int l, int r)
{
    if(l == r)
    {
        tree[rt] = node((s[l - 1] - 'a' + 1) * p[l - 1], (s[r - 1] - 'a' + 1) * p[n - r]);
        return ;
    }
    int mid = MID;
    build_tree(Lson);
    build_tree(Rson);
    pushup(rt);
}
void update_pos(int rt, int l, int r, int pos, ull val)
{
    if(l == r)
    {
        tree[rt] = node(val * p[l - 1], val * p[n - r]);
        return ;
    }
    int mid = MID;
    if(pos <= mid) update_pos(Lson, pos, val);
    else update_pos(Rson, pos, val);
    pushup(rt);
}
node query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && qr >= r)
        return tree[rt];
    int mid = MID;
    if(qr <= mid) return query(QL);
    else if(ql > mid) return query(QR);
    else return query(QL) + query(QR);
}
int main()
{
    scanf("%s", s);
    n = strlen(s);
    init();
    build_tree(1, 1, n);
    scanf("%d", &m); getchar();
    char q[20];
    while(m -- )
    {
        scanf("%s", q);
        if(q[0] == 'p')
        {
            int ql, qr; scanf("%d%d", &ql, &qr);
            if(qr - ql + 1 == 1)
            {
                printf("Yes\n");
                continue;
            }
            int md = (ql + qr) >> 1;
            node ans1, ans2;
            if((qr - ql + 1) & 1)
            {
                ans1 = query(1, 1, n, ql, md - 1);
                ans2 = query(1, 1, n, md + 1, qr);
            }
            else
            {
                ans1 = query(1, 1, n, ql, md);
                ans2 = query(1, 1, n, md + 1, qr);
            }
            if(ql - 1 <= n - qr)
                ans1.Lval *= p[(n - qr) - (ql - 1)];
            else
                ans2.Rval *= p[(ql - 1) - (n - qr)];
            printf("%s\n", ans[ans1.Lval == ans2.Rval]);
        }
        else
        {
            int pos; char tar[2];
            scanf("%d %s", &pos, tar);
            update_pos(1, 1, n, pos, (ull)(tar[0] - 'a' + 1));
        }
    }
    return 0;
}
/*
aaaaaabbbb
3
c 6 c
c 8 c
p 6 8
 */
发布了193 篇原创文章 · 获赞 58 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/104087725