• [国家集训队]最长双回文串(马拉车)


    传送门

    题意

    输入长度为n的串s,求s的最长双回文子串t,即t可分为两部分x和y且x和y都是回文串。

    题解

    考虑枚举中间的断点,所以我们只要记录以i为开头的最长回文串和以i为结尾的最长回文串。

    通过中心和长度求开头已经在 这篇 里面讲过了,这里不再赘述。结尾也只需自己慢漫推一推也可出来。

    可是以某个位置为开头的最长回文串不一定是某个中心的最长回文串的开头,其实它还有可能是某个中心的最长回文串的一部分。

    我们只需令第i个位置的值和第i-1个位置的值-2比较取最大即可。

    同理以某个位置为结束的最长回文串也类似。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N = 200010;
    int n, n0, id, mx;
    int p[N];
    char s[N], a[N];
    int l[N], r[N], ans;
    int main() {
        scanf("%s", s + 1);
        n = strlen(s + 1);
        n0 = 0;
        a[++n0] = '$';
        for (int i = 1; i <= n; i++) a[++n0] = '#', a[++n0] = s[i];
        a[++n0] = '#';
        id = mx = 0;
        for (int i = 1; i <= n0; i++) {
            p[i] = mx > i ? min(mx - i, p[id * 2 - i]) : 1;
            while (a[i + p[i]] == a[i - p[i]]) ++p[i];
            if (mx < i + p[i]) mx = i + p[i], id = i;
            l[(i - p[i]) / 2 + 1] = max(l[(i - p[i]) / 2 + 1], p[i] - 1);
            r[(i - p[i]) / 2 + p[i] - 1] = max(r[(i - p[i]) / 2 + p[i] - 1], p[i] - 1);
        }
        for (int i = 2; i <= n; i++) {
            l[i] = max(l[i], l[i - 1] - 2);
        }
        for (int i = n - 1; i >= 1; i--) {
            r[i] = max(r[i], r[i + 1] - 2);
        }
        for (int i = 1; i < n; i++) {
            ans = max(ans, l[i + 1] + r[i]);
        }
        cout << ans;
        return 0;
    }
  • 相关阅读:
    Equal Cut
    【线段树】Interval GCD
    zookeeper错误
    HBase之过滤器
    Hbase之缓存扫描加快读取速度
    Hbase之遍历超时处理
    Hbase之遍历获取数据
    Hbase之使用回调函数进行批处理操作
    Hbase之进行批处理操作
    Hbase之原子性更新数据
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12558185.html
Copyright © 2020-2023  润新知