最長雙迴文串 HYSBZ
阿新 • • 發佈:2019-01-06
思路:套用迴文串的模板求出最長迴文串之後, 用兩個陣列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; }