字符串中最長的迴文子串問題

此題參考


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;            //返回最長子串長度
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章