D. Non-Palindromic Substring

D. Non-Palindromic Substring

A string t is said to be k-good if there exists at least one substring of length k which is not a palindrome. Let f(t) denote the sum of all values of k such that the string t is k-good.

You are given a string s of length n. You will have to answer q of the following queries:

  • Given l and r (l<r), find the value of f(slsl+1sr).

A substring of a string z is a contiguous segment of characters from z. For example, "defor", "code" and "o" are all substrings of "codeforces" while "codes" and "aaa" are not.

A palindrome is a string that reads the same backwards as forwards. For example, the strings "z", "aa" and "tacocat" are palindromes while "codeforces" and "ab" are not.

Input

Each test contains multiple test cases. The first line contains a single integer t (1t2104) — the number of test cases. The description of the test cases follows.

The first line of each test case contains two integers n and q (2n2105,1q2105), the size of the string and the number of queries respectively.

The second line of each test case contains the string s. It is guaranteed the string s only contains lowercase English characters.

The next q lines each contain two integers, l and r (1l<rn).

It is guaranteed the sum of n and the sum of q both do not exceed 2105.

Output

For each query, output f(slsl+1sr).

Example

input

5
4 4
aaab
1 4
1 3
3 4
2 4
3 2
abc
1 3
1 2
5 4
pqpcc
1 5
4 5
1 3
2 4
2 1
aa
1 2
12 1
steponnopets
1 12

output

9
0
2
5
5
2
14
0
2
5
0
65

Note

In the first query of the first test case, the string is aaab. aaab, aab and ab are all substrings that are not palindromes, and they have lengths 4, 3 and 2 respectively. Thus, the string is 2-good, 3-good and 4-good. Hence, f(aaab)=2+3+4=9.

In the second query of the first test case, the string is aaa. There are no non-palindromic substrings. Hence, f(aaa)=0.

In the first query of the second test case, the string is abc. ab, bc and abc are all substrings that are not palindromes, and they have lengths 2, 2 and 3 respectively. Thus, the string is 2-good and 3-good. Hence, f(abc)=2+3=5. Note that even though there are 2 non-palindromic substrings of length 2, we count it only once.

 

解题思路

  为了方便规定字符串的下标从 0 开始,询问的 lr 也相应的映射到 0n1 范围内。

  对于询问 lr,子串的长度为 len=rl+1。先考虑 k[2,len1] 的情况。命题存在长度为 k 的非回文串,对应的反命题就是不存在长度为 k 的非回文串,等价于所有长度为 k 的子串都是回文串。如果 k 能作为答案,意味着原命题要成立,反命题不成立;否则反命题成立。所以我们现在要验证反命题是否成立(反命题会比原命题好验证)。

  如果所有长度为 k 的子串都是回文串,如果 k 是奇数,可以推出 sl=sl+2=sl+4=sl+1=sl+3=sl+5=,即下标奇偶性相同的字符都相同。此时反命题成立,所有奇数的 k 都无法作为答案。如果 k 是偶数,可以推出 sl=sl+1==sr,即所有字符都相同,此时反命题成立,所有偶数 k 都无法作为答案。

  要判断上述两种情况是否成立,只需预处理出 f(i) 表示左边所有下标中第一个与 si 不同的下标,g(i) 表示左边所有与 i 奇偶性相同的下标中第一个与 si 不同的下标。如果 f(r)<l 说明第二种情况成立,否则假设不超过 len1 的最大偶数为 t=len1(len1mod2),答案加上 2+4++t=t2(t2+1)。如果 g(r)<lg(r1)<l 说明第一种情况成立,否则假设不超过 len1 的最大奇数为 t=len1(lenmod2),答案加上 3+5++t=(t+12)21

  剩下就是 k=1k=len 的情况。显然 k=1 不可能作为答案,因为长度为 1 的串必定是回文串。而长度为 len 的整个串则需要单独判断是否为回文串,可以用 Manacher 算法(字符串哈希貌似会被卡自然溢出,或者用双哈希也可以)。

  AC 代码如下,时间复杂度为 O(n+m)

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

typedef long long LL;

const int N = 2e5 + 5, M = N * 2;

int n, m;
char s[N], t[M];
int d[M];
int f[N], g[N];

void manacher() {
    int m = 0;
    t[m++] = '#';
    for (int i = 0; i < n; i++) {
        t[m++] = s[i];
        t[m++] = '#';
    }
    for (int i = 0, j = 0; i < m; i++) {
        if (i < j + d[j]) d[i] = min(d[2 * j - i], j + d[j] - i);
        else d[i] = 1;
        while (i - d[i] >= 0 && i + d[i] < m && t[i - d[i]] == t[i + d[i]]) {
            d[i]++;
        }
        if (i + d[i] > j + d[j]) j = i;
    }
}

void solve() {
    scanf("%d %d %s", &n, &m, s);
    for (int i = 0; i < n; i++) {
        if (i - 1 >= 0 && s[i] == s[i - 1]) f[i] = f[i - 1];
        else f[i] = i - 1;
        if (i - 2 >= 0 && s[i] == s[i - 2]) g[i] = g[i - 2];
        else g[i] = i - 2;
    }
    manacher();
    while (m--) {
        int l, r;
        scanf("%d %d", &l, &r);
        l--, r--;
        LL ret = 0;
        if (f[r] >= l) {
            LL t = r - l - (r - l) % 2;
            ret += t * (t + 2) / 4;
        }
        if (g[r] >= l || g[r - 1] >= l) {
            LL t = r - l - (r - l + 1) % 2;
            ret += (t + 1 >> 1) * (t + 1 >> 1) - 1;
        }
        if (d[l + r + 1] <= r - l + 1) ret += r - l + 1;
        printf("%lld\n", ret);
    }
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round #934 (Div1, Div2) Editorial:https://codeforces.com/blog/entry/127195

posted @   onlyblues  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2023-04-04 方格迷宫
2023-04-04 砝码称重
2023-04-04 C. Place for a Selfie
2023-04-04 D. A Wide, Wide Graph
2022-04-04 牛奶工厂
Web Analytics
点击右上角即可分享
微信分享提示