[hihoCoder 1032]最长回文子串[Manacher]

题目链接: [hihoCoder 1032]最长回文子串[Manacher]

题意分析:

求给定字符串中的最长回文串的长度是多少。

解题思路:

暴力:枚举每个区间,判断回文串,复杂度O(n3)

枚举中心:分奇偶性讨论,从中心往两边扫,复杂度O(n2)

Manacher:复杂度O(n)

本题最坏情况下,1e6,所以只能使用Manacher了。

推荐个博文:Manacher算法总结

个人感受:

时隔7个月,重拾。:-)

具体代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 1e6 + 111;

char Ma[MAXN * 2];
int Mp[MAXN * 2], ans;

void Manacher(char s[], int len)
{
    int l = 0;
    Ma[l++] = '$'; Ma[l++] = '#';
    for (int i = 0; i < len; ++i)
    {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = 0; // Ma[0] 和 Ma[l] 赋值后可以防止后期匹配越界

    int mx = 0, id = 0; // mx: id最长延伸到的位置 id: mx的中心位置

    for (int i = 0; i < l; ++i)
    {
        // 三种情况:1.i对称位置回文在mx范围之内
        //           2.i对称位置回文部分在mx范围之内
        //           3.i位置直接在mx范围之外,直接从i开始匹配
        Mp[i] = mx > i ? min(Mp[2 * id - i], mx - i) : 1;

        while (Ma[i + Mp[i]] == Ma[i - Mp[i]]) ++Mp[i];
        ans = max(ans, Mp[i] - 1);
        if (i + Mp[i] > mx)
        {
            mx = i + Mp[i];
            id = i;
        }
    }
}

int main()
{
    int t; scanf("%d", &t);
    char s[MAXN];
    while (t --)
    {
        scanf("%s", &s);
        ans = 0;
        Manacher(s, strlen(s));
        printf("%d\n", ans);
    }
    return 0;
}


O(n2)算法(不保证AC,但保证能T,2333):

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int MAXN = 1000010;
typedef long long ll;
int dp_ou[MAXN], dp_ji[MAXN];

int main() {
    ios_base::sync_with_stdio(0);
    string a;
    int t;
    cin >> t;
    while (t--){
        memset(dp_ou, 0, sizeof dp_ou);
        fill(dp_ji, dp_ji + MAXN, 1);
        cin >> a;
        ll length = a.length();
        int ans = 0;
        for (int i = 0; i < length; ++i){
            for (int l = i - 1, r = i + 1; l >= 0 && r < length; --l, ++r){
                if (a[l] == a[r]){
                    dp_ji[i] += 2;
                    ans = max(ans, dp_ji[i]);
                }
                else break;
            }
            for (int l = i, r = i + 1; l >= 0 && r < length; --l, ++r){
                if (a[l] == a[r]){
                    dp_ou[i] += 2;
                    ans = max(ans, dp_ou[i]);
                }
                else break;
            }
        }
        cout << ans << '\n';
    }
    return 0;
}



你可能感兴趣的:(Manacher)