Hdu 3068 Manacher演算法求最長迴文串長度
阿新 • • 發佈:2019-01-27
最長迴文
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
想法:只要理解了Manacher演算法就很簡單了。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <map>
#include <iostream>
using namespace std;
char str[2*110000+10];
int p[10+2*110000];
//因為添加了一倍的特殊字元,所以要乘2.
char s[10+110000];
//原字串。
int len;
void manacher(int len)
{
str[0]='$';str[1]='#' ;
//str[0]是為了不讓陣列越界,至於‘$’和‘#’可以由不與原字串重複的任意特殊字元代替。
for(int i=0;i<len;i++)
str[2*(i+1)]=s[i],str[2*(i+1)+1]='#';
//為了排除奇長度與偶長度字串的區別。
str[2*len+2]='\0';
len=2*len+2;
int id=0,mx=0;
p[0]=0;
for(int i=1;i<len;i++)
{
if(i>=p[id]+id)
//超過了以id為中心的最長迴文串的右邊界。
p[i]=1;
else
p[i]=min(p[2*id-i],mx-i);
//如果沒有,請看連結中的圖文解釋(我實在想不出比他更好的了,就不獻醜了)。
while(str[i-p[i]]==str[i+p[i]])
p[i]++;
if(p[i]+i>mx)
//更新最長迴文串長度。
mx=p[i]+i,id=i;
}
}
int main()
{
while (~scanf("%s",s)) {
len = strlen(s);
manacher(len);
int ans = 0;
for (int i = 0; i<2*len+2; i++) {
ans = max(ans,p[i]);
}
printf("%d\n",ans-1);
//減一很重要,可以自己手動舉個例子試試。