最長回文 Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Practice HDU 3068
Description
給出一個隻由小寫英文字元a,b,c...y,z組成的字元串S,求S中最長回文串的長度.
回文就是正反讀都是一樣的字元串,如aba, abba等
Input
輸入有多組case,不超過120組,每組輸入為一行小寫英文字元a,b,c...y,z組成的字元串S
兩組case之間由空行隔開(該空行不用處理)
字元串長度len <= 110000
Output
每一行一個整數x,對應一組case,表示該組case的字元串中所包含的最長回文長度.
Sample Input
aaaa
abab
Sample Output
4
3
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 110005
char str[N];
char strf[2 * N];
int rad[2 * N];
int len;
void init(){
int i, j;
len = strlen(str);
strf[0] = '@';
strf[1] = '#';
for(i = 0; i < len; i ++){
strf[i * 2 + 2] = str[i];
strf[i * 2 + 3] = '#';
}
strf[len * 2 + 2] = '$';
len = len * 2 + 3;
}
int main(){
while(~scanf("%s", str)){
init();
//cout << strf << endl;
memset(rad, 0, sizeof(rad));
int mx = 0, id;
int len = strlen(strf);
for(int i = 1; i < len - 1; i++){
if(mx > i)
rad[i] = min(rad[2 * id - i], rad[id] + id - i);
else
rad[i] = 1;
while(strf[i + rad[i]] == strf[i - rad[i]])
rad[i]++;
if(rad[i] + i > mx){
mx = rad[i] + i;
id = i;
}
}
int ans = 0;
for(int i = 0; i < len; i ++){
//printf("%d\n", rad[i]);
if(rad[i] > ans)
ans = rad[i];
}
printf("%d\n", ans - 1);
}
return 0;
}
manacher部分還可以寫成如下形式,個人認為更容易了解(參考點選打開連結),不過注意到最後ans不用再減一
for(int i = 1, j = 0, k; i < len;){
while(strf[i - j - 1] == strf[i + j + 1])
j ++;
rad[i] = j;
for(k = 1; k <= j && rad[i - k] != rad[i] - k; k ++){
rad[i + k] = min(rad[i - k], rad[i] - k);
}
i += k;
j = max(j - k, 0);
}