雖然在題目中, 這類算法出現得比較少,
但其效率的確很好並且不是很難懂, 所以學一下也總有用得到的時候;
下面是一篇不錯的博客, 推薦;
http://www.open-open.com/lib/view/open1419150233417.html
for(; s[i - len[i]] == s[i + len[i]]; len[i]++);
並說明一下, 有些讀者認爲這句話沒有意義但實際上
我們設當前正匹配i位置, 找到的最遠的地方max_dist(即當前找出的longest迴文串所到達的地方)設中心點爲id,max_dist 的對應點Min_dist,
i關於id對應的點是j, 所以我們用j來更新len【i】, 有的讀者可能認爲只要len【j】正確, 計算len【i】是不需要這句話的。
其實不然, 因爲如果迴文串的部分超過min_dist的話是無法保證超出的部分在id的另一側是對稱的, 所以這一句話相當有必要;
給出裸題
HDU 3068代碼
#include <bits/stdc++.h>
using namespace std;
#define N 110005
#define rep(i, s, t) for(int i = s, end = t; i <= end; ++i)
struct Manacher{
int len, p[N<<1], res = -1;
char s[N<<1], str[N];
void read() {
res = -1;
len = strlen(str);
s[0] = '$';
rep(i, 0, len - 1)
s[i<<1|1] = '#', s[(i+1)<<1] = str[i];
s[len<<1|1] = '#';
}
void match() {
int Max_dist = 0, id;
rep(i, 1, len<<1|1) {
if(Max_dist > i) p[i] = min(Max_dist - i, p[2*id-i]);
else p[i] = 1;
for(; s[i - p[i]] == s[i + p[i]]; p[i]++);
if(p[i] + i >Max_dist) Max_dist = p[i] + i, id = i;
}
}
int solve() {
read();
match();
rep(i, 1, len<<1|1)
res = max(res, p[i] - 1);
return res;
}
}M;
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("result.out", "w", stdout);
#endif
while(scanf("%s", M.str) != EOF){
printf("%d\n", M.solve());
}
return 0;
}