hdu 3068 最长回文(马拉车)

Posted jpphy0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3068 最长回文(马拉车)相关的知识,希望对你有一定的参考价值。

问题

hdu 3068 最长回文 - https://acm.hdu.edu.cn/showproblem.php?pid=3068

分析

  • 暴力搜索(tle)
  • 马拉车O(n)

代码

  • 暴力搜索
#include<bits/stdc++.h>
using namespace std;
const int MXN = 1e5+10;
char s[MXN];
int expand(int l, int r){ // 扩展
    while(s[l] && s[r] && s[l] == s[r]) --l, ++r;
    return r - l - 1;
}
int main(){
    int t, l, r, ans;
    scanf("%d", &t);
    while(t--){
        scanf("%s", s+1), s[0] = '\\0';
        l = 1, r = 1, ans = 0;
        while(s[l] && s[r]) // 两种扩展方式的初始条件:l == r 或者 r == l+1
            ans = max(ans, expand(l, r)), l == r ? ++r : ++l;
        printf("%d\\n", ans);
    }
    return 0;
}
  • Manacher(马拉车)
/* hdu 3068 最长回文 */
#include<bits/stdc++.h>
using namespace std;
const int MXN = 1.1e5+10;
char s[MXN<<1];
int R; // R是递推过程中所有出现过的对称区间的最大右边界
int p; // 与R对应的对称中心
int len[MXN<<1]; // len[i]:最大回文长度,i是回文串的对称中心(变换后的字符串)
int manacher(int n){
    int res = 0;
    for(int l, r, i = 1; i <= n; ++i){// l,r是以i为中心的对称边界
        if(i >= R) l = i, r = i; // i是对称中心,也是对称边界
        else r = min(R, i + len[(p<<1)-i]), l = (i << 1) - r;// 设定对称边界
        while(s[l-1] && s[r+1] && s[l-1] == s[r+1]) ++r, --l;// 暴力扩展
        if(r >= R) R = r, p = i; // 更新最大右边界及对称中心
        len[i] = (r - l + 1) >> 1;
        res = max(res, len[i]);
    }
    return res;
}
int main(){
    int n;
    while(scanf("%s", s+MXN) == 1){
        n = strlen(s+MXN)+1, s[0] = '\\0'; // 设定一个结束符,用于扩展时比较
        for(int i = 1; i <= n; ++i) s[2*i-1] = '#', s[i<<1] = s[i+MXN-1];//变换字符串
        --n, p = 0, R = 0, len[0] = 0;
        printf("%d\\n", manacher(n<<1|1));
    }
    return 0;
}

以上是关于hdu 3068 最长回文(马拉车)的主要内容,如果未能解决你的问题,请参考以下文章

hdu3068 最长回文 马拉车模板题

HDU-3068-最长回文-马拉车算法模板题

manacher算法 O(n) 求字符串中最长回文子串 hdu 3068(模板题)

HDU 3068

manacher马拉车算法

马拉车算法 HDU3068