hdu 3068 最長迴文(Manacher演算法入門模板題)+解題套路
阿新 • • 發佈:2019-02-01
輸入有a~z組成的字串,輸出最長迴文子串的長度
*Manacher演算法模板 ==> 一個專用於求最長迴文串的演算法
1、轉化字串:abcba ==> $#a#b#c#b#a#(前面加$防止陣列溢位)
2、s: $ # a # b # c # b # a #
p: 1 2 1 2 1 6 1 2 1 2 1
p[i]的含義:以s[i]為中心的迴文串右擴張的最長長度,p[i] - 1就是轉化前的字串以i為中心的迴文子串的長度
3、求p[],設id為迴文子串的中心,mx為邊界,則mx = id + p[id],i與j關於id對稱
(1)id<i<mx
==>p[j] < mx-i
整張圖是關於id對稱的,所以p[i] = p[i]
==>p[j]>=mx-i
此時p[i] = mx-i
(2)i>=mx
這裡的p[i]初始值只能是1,通過後續計算慢慢累加
void getp() { memset(p, 0, sizeof(p)); int id = 0, mx = 0; for(int i=1; i<len; i++) { int j = 2*id-i; p[i] = mx>i ? min(p[j], mx-i):1; while(s[i+p[i]] == s[i-p[i]]) p[i]++; if(i+p[i] > mx) { mx = i+p[i]; id = i; } } }
所以本題的完整程式碼就是:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> using namespace std; #define inf 310010 char s[inf], str[inf]; int p[inf], len; void gets() { int li = strlen(str); len = 0; s[len++] = '&'; s[len++] = '#'; for(int i=0; i<li; i++) { s[len++] = str[i]; s[len++] = '#'; } } void getp() { gets(); memset(p, 0, sizeof(p)); int id = 0, mx = 0; for(int i=1; i<len; i++) { int j = 2*id-i; p[i] = mx>i ? min(p[j], mx-i):1; while(s[i+p[i]] == s[i-p[i]]) p[i]++; if(i+p[i] > mx) { mx = i+p[i]; id = i; } } } int main() { while(~scanf("%s", str)) { getp(); int ans=1; for(int i=0; i<len; i++) ans = max(ans, p[i]-1); printf("%d\n", ans); } return 0; }