E - 最長雙迴文串 HYSBZ - 2565

思路:套用迴文串的模板求出最長迴文串之後, 用兩個數組L與R分別存 最長迴文串右邊界在當前節點的最長迴文串長度,以及左邊界在當前節點的最長迴文串長度。然後分別在掃描一下兩個數組,得到迴文串左右邊界在當前節點的最長迴文串長度。然後取最大值就好了。

#include <iostream>
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int Max_N = 500000+100;
int Ma[Max_N * 2];
int Mp[Max_N * 2];
void Manacher(char s[], int len)
{
    int l = 0;
    Ma[l++] = 1010;
    Ma[l++] = 1000;
    for (int i = 0; i < len; i++) {
        Ma[l++] = int(s[i]);
        Ma[l++] = 1000;
    }
    Ma[l] = 0;
    int mx = 0, id = 0;
    for (int i = 0; i < l; i++) {
        Mp[i] = mx > i? min(Mp[2*id-i], mx-i):1;
        while (Ma[i+Mp[i]] == Ma[i-Mp[i]]) Mp[i]++;
        if (i + Mp[i] > mx) {
            mx = i + Mp[i];
            id = i;
        }
    }
}
char buf[Max_N];
int l[Max_N];
int r[Max_N];
int n;
int main()
{
    while (scanf("%s", buf) != EOF) {
        Manacher(buf, strlen(buf));
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        int len = strlen(buf);
        int max1 = 0;
        for (int i = 0; i < 2*len+2; i++) {
            int s = Mp[i] - 1 + i;
            int s2 = i - Mp[i] + 1;
            l[s] = max(l[s], Mp[i] - 1);
            r[s2] = max(r[s2], Mp[i] - 1);
     
        } 
        int ss1 = 0; 
        for (int i = 2*len + 1; i >= 0; i--) {
            if (ss1 != 0) {
                ss1--;
                l[i] = max(l[i], ss1);
                ss1 = l[i];
            }
            else ss1 = l[i];
        }
        ss1 = 0;
        for (int i = 0; i < len * 2 + 2; i++) {
            if (ss1 != 0) {
                ss1--;
                r[i] = max(r[i], ss1);
                ss1 = r[i];
            }
            else ss1 = r[i];
        }
        for (int i = 0; i < 2*len + 2; i++) {
            max1 = max(max1, l[i] + r[i]);
        }
        printf("%d\n", max1);
    }
     
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章