• luoguP4555 [国家集训队]最长双回文串 manacher算法


    不算很难的一道题吧....

    很容易想到枚举断点,之后需要处理出以$i$为开头的最长回文串的长度和以$i$为结尾的最长回文串的长度

    分别记为$L[i]$和$R[i]$

    由于求$R[i]$相当于把$L[i]$反过来求一遍,因此只需考虑求$L[i]$

    考虑$manacher$算法

    我们注意到,当$mr$扩展时,第一个把$mr$扩展到$i$的中心$j$构成的串就是$L[i]$

    在$manacher$算法中统计一下即可

    复杂度$O(n)$

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define ll long long
    #define ri register int
    #define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
    #define drep(io, ed, st) for(ri io = ed; io >= st; io --)
        
    const int sid = 2e5 + 1e4;
    
    char s[sid], t[sid];
    int n, m, r[sid], L[sid], R[sid];
    
    void manacher(char *s, int *lst, int opt) {
        r[1] = 1; lst[1] = 1;
        int mr = 1, pos = 1;
        rep(i, 2, m) {
            r[i] = min(mr - i + 1, r[pos + pos - i]);
            while(i - r[i] > 0 && s[i + r[i]] == s[i - r[i]]) 
                lst[i + r[i]] = 2 * r[i] + 1, r[i] ++;
            if(i + r[i] - 1 > mr) mr = i + r[i] - 1, pos = i;
        }
        if(opt) reverse(lst + 1, lst + m + 1);
    }
    
    int main() {
        scanf("%s", s + 1);
        n = strlen(s + 1);
        
        rep(i, 1, n) t[++ m] = '#', t[++ m] = s[i];
        t[++ m] = '#';
        
        
        reverse(t + 1, t + m + 1);
        manacher(t, R, 1);
        reverse(t + 1, t + m + 1);
        manacher(t, L, 0);
    
        int ans = 0;
        rep(i, 1, m)
            if(t[i] == '#') 
                ans = max(ans, (L[i] + R[i] - 1) / 2);
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    ie用document.getElementsByName获取不到
    js_设置光标到文本的最后位置
    js-转大小写
    mysql查询数据表的路径
    myeclipse导出javadoc时特殊字符 尖括号
    keyCode码集合
    mysql查询数据库约束
    oracle查询每个表的占用空间
    MYSQL复制表
    MacOs上的Intellij idea高频快捷键总结(2018.1版本)
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9964653.html
Copyright © 2020-2023  润新知