首页 > 其他分享 >F - Palindrome Query

F - Palindrome Query

时间:2023-12-03 18:44:56浏览次数:25  
标签:Palindrome th leq 哈希 query 字符串 Query Yes

F - Palindrome Query

Problem Statement

You are given a string $S$ of length $N$ consisting of lowercase English letters.
Process $Q$ queries described below in the order they are given.
There are two types of queries:

  • 1 x c : Change the $x$-th character of $S$ to the lowercase English letter $c$.
  • 2 L R : If the substring formed by the $L$-th through $R$-th characters of $S$ is a palindrome, print Yes; otherwise, print No.

Constraints

  • $1 \leq N \leq 10^6$
  • $1 \leq Q \leq 10^5$
  • $S$ is a string of length $N$ consisting of lowercase English letters.
  • $1 \leq x \leq N$
  • $c$ is a lowercase English letter.
  • $1 \leq L \leq R \leq N$
  • $N, Q, x, L, R$ are integers.

Input

The input is given from Standard Input in the following format. Here, $\text{query}_i$ is the $i$-th query to be processed.

$N$ $Q$
$S$
$\text{query}_1$
$\text{query}_2$
$\vdots$
$\text{query}_Q$

Each query is given in one of the following formats:

$1$ $x$ $c$

$2$ $L$ $R$

Output

Follow the instructions in the problem statement and print the answers to the queries, separated by newlines.


Sample Input 1

7 8
abcbacb
2 1 5
2 4 7
2 2 2
1 5 c
2 1 5
2 4 7
1 4 c
2 3 6

Sample Output 1

Yes
No
Yes
No
Yes
Yes

Initially, $S =$ abcbacb.
For the first query, the string formed by the $1$-st through $5$-th characters of $S$ is abcba, which is a palindrome. Thus, print Yes.
For the second query, the string formed by the $4$-th through $7$-th character of $S$ is bacb, which is not a palindrome. Thus, print No.
For the third query, the string formed by the $2$-nd through $2$-nd character of $S$ is b, which is a palindrome. Thus, output Yes.
For the fourth query, change the $5$-th character of $S$ to c. $S$ becomes abcbccb.
For the fifth query, the string formed by the $1$-st through $5$-th character of $S$ is abcbc, which is not a palindrome. Thus, output No.
For the sixth query, the string formed by the $4$-th through $7$-th character of $S$ is bccb, which is a palindrome. Thus, output Yes.
For the seventh query, change the $4$-th character of $S$ to c. $S$ becomes abccccb.
For the eighth query, the string formed by the $3$-rd through $6$-th character of cccc, which is a palindrome. Thus, output Yes.

 

解题思路

  做法是用线段树来维护子串的字符串哈希值。

  对于字符串 $s$ 的子串 $s[l,r] = s_l, s_{l+1}, \ldots, s_r$,将其翻转得到 $s'[l,r] = s_r, s_{r-1}, \ldots, s_l$,那么子串 $s[l,r]$ 是回文串等价于 $s[l,r] = s'[l,r]$。对与判断两个字符串是否相同可以转而判断两个字符串的字符串哈希是否相同,其中 $s[l,r]$ 的字符串哈希值是$$\sum\limits_{i=l}^{r}{s_i \times P^{(r-i)}} \pmod{2^{64}-1}$$

  一般取 $P = 13331$,$s_i$ 指字符对应的 ASCII 码。

  同理 $s'[l,r]$ 的字符串哈希值是$$\sum\limits_{i=l}^{r}{s_i \times P^{(i-l)}} \pmod{2^{64}-1}$$

  我们只需要用线段树来维护某个区间所表示的子串和其翻转后的子串的字符串哈希值即可,线段树实现支持的操作有单点修改,区间查询。即对于表示区间 $[l,r]$ 的节点,维护 $s[l,r]$ 的字符串哈希值 $h_1$,$s'[l,r]$ 的字符串哈希值 $h_2$。节点的更新操作相当于将左右儿子的字符串拼接然后求字符串哈希。对于 $h_1$,假设其左儿子维护的 $s[l, \text{mid}]$ 的字符串哈希值是 $h'_1$,右儿子维护的 $s[\text{mid}+1, r]$ 的字符串哈希值是 $h''_1$,则有 $h_1 = h'_1 \times P^{r - \text{mid}} + h''_1$。同理有 $h_2 = h''_2 \times P^{\text{mid} - l + 1} + h'_2$。查询操作就是询问子串 $s[l,r]$ 的 $h_1$ 和 $s'[l,r]$ 的 $h_2$ 是否相同。

  AC 代码如下,时间复杂度为 $O(n + q \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ULL;

const int N = 1e6 + 10, P = 13331;

char s[N];
ULL p[N];
struct Node {
    int l, r;
    ULL h1, h2;
}tr[N * 4];

void pushup(int u) {
    tr[u].h1 = tr[u << 1].h1 * p[tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1] + tr[u << 1 | 1].h1;
    tr[u].h2 = tr[u << 1 | 1].h2 * p[tr[u << 1].r - tr[u << 1].l + 1] + tr[u << 1].h2;
}

void build(int u, int l, int r) {
    tr[u] = {l, r};
    if (l == r) {
        tr[u].h1 = tr[u].h2 = s[l];
    }
    else {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int x, int c) {
    if (tr[u].l == tr[u].r) {
        tr[u].h1 = tr[u].h2 = c;
    }
    else {
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(u << 1, x, c);
        else modify(u << 1 | 1, x, c);
        pushup(u);
    }
}

Node query(int u, int l, int r) {
    if (tr[u].l >= l && tr[u].r <= r) return tr[u];
    int mid = tr[u].l + tr[u].r >> 1;
    if (r <= mid) return query(u << 1, l, r);
    else if (l >= mid + 1) return query(u << 1 | 1, l, r);
    Node t1 = query(u << 1, l, r), t2 = query(u << 1 | 1, l, r);
    ULL h1 = t1.h1 * p[t2.r - t2.l + 1] + t2.h1;
    ULL h2 = t2.h2 * p[t1.r - t1.l + 1] + t1.h2;
    return {t1.l, t2.r, h1, h2};
}

int main() {
    int n, m;
    scanf("%d %d %s", &n, &m, s + 1);
    p[0] = 1;
    for (int i = 1; i <= n; i++) {
        p[i] = p[i - 1] * P;
    }
    build(1, 1, n);
    while (m--) {
        int op;
        scanf("%d", &op);
        if (op == 1) {
            int x;
            char c[5];
            scanf("%d %s", &x, c);
            modify(1, x, c[0]);
        }
        else {
            int l, r;
            scanf("%d %d", &l, &r);
            Node t = query(1, l, r);
            printf("%s\n", t.h1 == t.h2 ? "Yes" : "No");
        }
    }
    
    return 0;
}

 

参考资料

  Editorial - Daiwa Securities Co. Ltd. Programming Contest 2023(AtCoder Beginner Contest 331):https://atcoder.jp/contests/abc331/editorial/7876

标签:Palindrome,th,leq,哈希,query,字符串,Query,Yes
From: https://www.cnblogs.com/onlyblues/p/17873444.html

相关文章

  • ABC 331 F - Palindrome Query(字符串哈希,树状数组)
    字符串哈希[OI-Wiki](字符串哈希-OIWiki(oi-wiki.org))分为两种哈希方式:以左为高位和以右为高位如果只是快速查询每个字串的哈希值,用以左为高位比较简单,即\[Hash[l...r]=Hash[1...r]-Hash[1...(l-1)]\timesbase^{r-l+1}\]但是如果有修改操作,需要将每一位的Hash值存......
  • Jquery - 学习笔记
    1.Jquery的下载与安装1.1下载https://jquery.com/1.2安装<!doctypehtml><htmllang="zh/cn"><head><metacharset="UTF-8"><title>jquerylearn</title></head><body><!--引入jquery-->&......
  • 一列拆分成两列(BT拆)(Power Query)
    问题:左表转成右表let源=Excel.CurrentWorkbook(){[Name="表1"]}[Content],分组的行=Table.Group(源,{"机房名称","网络制式"},{"合并",eachText.Combine([BBU名称],",")}),按分隔符拆分列=Table.SplitColumn(分组的行,"合并"......
  • 在线axios,jquery库
    点击查看代码<head><metacharset="UTF-8"><title>Title</title><scriptsrc="https://unpkg.com/axios/dist/axios.min.js"></script><scripttype="text/javascript"src="https......
  • CF1827C Palindrome Partition 题解
    题目链接点击打开链接题目解法首先考虑一个朴素的\(dp\)令\(f_i\)表示以\(i\)结尾的合法子串的个数为了不重不漏,我们令\(le_i\)表示以\(i\)为右端点,离\(i\)最近的偶回文串的左端点,然后不难得到转移为\(f_i=f_{le_i-1}+1\)为什么不会漏?考虑以\(i\)为右端点,且比......
  • [翻译]——How the MySQL Optimizer Calculates the Cost of a Query (Doc ID 1327497
    本文是对这篇文章HowtheMySQLOptimizerCalculatestheCostofaQuery(DocID1327497.1)[1]的翻译,翻译如有不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处。谢谢!适用于:MySQL4.0及后续更高的版本本文档中的内容适用于任何平台。目标了解MySQL优化器如......
  • SpringBoot JPA实践之EntityManage查询返回自定义DTO entityManager.createNativeQuer
    SpringBootJPA实践之EntityManage查询返回自定义DTOentityManager.createNativeQuery(sql)  在很多时候我更喜欢随意组合查询出来返回一个DTO对象的实现,JPA提供的多数查询均以返回Entity居多,它提供的EntityManager对象可以实现将SQL语句查询的结果转换为自定义DTO对象(这与......
  • SQL SERVER JSON_QUERY JSON_VALUE
    response_json:{"code":"000","message":"成功","data":{"secretKey":"","content":"{\"rule_result\":{\"risk_level\&q......
  • Elasticsearch query查询语法 es
    Elasticsearch查询语法1.查询基本语法结构GET/{索引名}/_search{ "from":0,//返回搜索结果的开始位置 "size":10,//分页大小,一次返回多少数据 "_source":[...需要返回的字段数组...], "query":{...query子句...}, "aggs":{..aggs子句..},......
  • JQuery获取select点击option的data-*属性
    <optionvalue="33333"data-socketid="1111"data-numnew="22222">4444</option>$(document).on('change','#institute-select',function(){//这里是重点,使用attr来获取vari......