Manache算法,網上很多網友都說需要在轉換後的字符串(即是在字符串中添加了‘#’)的最前面加上一個額外的字符,但是我覺得沒有必要這麼做: 最初的時候我選擇第二個字符作爲mid 然後尋找後面是否有更適合做mid的字符,如果有則替換。
具體代碼實現如下:
#include <stdio.h>
#include <string.h>
#define MIN(a,b) ((a)>(b)?(b):(a))
void FullStr(char*res,char*des);
int FindMaxLen(char*res,int Len);
int main()
{
char Res[1000],Des[1000];
while (scanf("%s",Res)!=EOF)
{
FullStr(Res,Des);
printf("%d\n",FindMaxLen(Des,strlen(Des)));
}
return 0;
}
//講原字符串中添加上‘#’使得奇數和偶數個字符可以按照相同的方式處理。
void FullStr(char*res,char*des)
{
int j=0;
for (int i=0;res[i]!='\0';i++)
{
des[j++]='#';
des[j++]=res[i];
}
des[j++]='#';
des[j]='\0';
}
//尋找最大的迴文子串的長度
int FindMaxLen(char*res,int Len)
{
int P[2000]={0};
int max=2; //max代表最右邊的最長子串的下標
int id=1; //最初的時候選擇第二個字符作爲最長子串的中間字符
P[0]=1;
P[1]=2;
for (int i=2;i<Len;i++)
{
if (max>i)
{
P[i]=MIN(max-i,P[2*id-i]); // 如果i在已有的最長子串的範圍內,則比較i的對稱點和i距離最長子串最右邊的距離,選擇較小者
}
else
{
P[i]=1;
}
while (i+P[i]<Len && i-P[i]>=0 && res[i+P[i]]==res[i-P[i]]) // i爲中心向兩邊擴展
{
P[i]++;
}
if (P[i]>max-id+1) //如果作爲中心的子串長度大於id爲中心的子串長度,則替換id和max
{
id=i;
max=id+P[i]-1;
}
}
return max-id; //返回最長子串長度
}