UVAlive 4975 Manacher+枚舉

題意:

題目鏈接:https://vjudge.net/problem/UVALive-4975
給出一個字符串,求形如XYXY的最長子串長度,其中Y時X的逆字符串。


思路:

一開始沒仔細想上來就二分hash,後來發現並不滿足二分條件。
正解是manacher預處理,然後暴力枚舉長度,枚舉時有講究,顯然長度一定時4的倍數,然後再看左右兩個子串的迴文串範圍。


代碼:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 10;

int n, l;
int len[MAXN << 1];
char a[MAXN], s[MAXN];

int manachar (char *p) {
    n = strlen (p), l = 0;
    s[l++] = '@';
    s[l++] = '#';
    for (int i = 0; i < n; i++) {
        s[l++] = p[i];
        s[l++] = '#';
    }
    s[l++] = '~'; s[l] = 0;
    //cout << s << endl;

    int Max = 0, pos = 0, ans = 0;
    for (int i = 1; i < l; i++) {
        if (Max > i) {
            len[i] = min (len[2 * pos - i], Max-i);
        }
        else
            len[i] = 1;
        while (s[i+len[i]] == s[i-len[i]])
            len[i]++;
        ans = max (ans, len[i]);
        if (len[i] + i > Max) {
            Max = len[i]+i;
            pos = i;
        }
    }
    return ans-1;
}

int main() {
    //freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", a);
        manachar(a);
        int ans = 0;
        for (int i = 1; i < l; i += 2) {
            int x = len[i] - 1;
            if (x < 4) continue;
            while (x % 4 != 0) x--;
            for (; x > ans; x -= 4) {
                int p1 = i - x / 2, p2 = i + x / 2;
                if (len[p1] - 1 >= x / 2 && len[p2] - 1 >= x / 2) {
                    ans = x;
                    break;
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章