在這裡,我就把用到的所有知識、我的思路和一些查到的資料分享給大家。
方法一、(台灣的那個研究生的思路)
step1:利用分治法或動態規劃法,找到這個字串中最長的回文子串行,記下它的長度,記為longest。(對於求longest的具體方法,王曉東的《演算法設計與分析》這本書上有詳細的解答)
step2:然後用遍歷的方法找出字串中所有可以構成回文子串行的1—pair回文序列,如「fdsf」中的「ff」,並進行序號標記。for(i=0;istep3:之後,將符合條件的1-pair不斷嵌入到另乙個1-pair中,直到longest/2-pair.條件符合是指若有1-pair回文子串行(i,j)和(m,n),當m>i&&j
方法二、(由字串中的最長回文子串行的思路拓展得到)
如上方法一所說,
對於求longest的具體方法,王曉東的《演算法設計與分析》這本書上有詳細的解答。那麼,如何拓展呢??(動態規劃法或者是分治法)
我們知道,最長回文子串行是採用規避兩端,考慮中間的策略。即若有字串string,長度為length,找出字串string[i:j]之間的最長回文子串行,則有f(i,j)為獲取函式:
當i>j時,f(i,j)=0。
當i=j時,f(i,j)=1。
當itring
[j]時,f(i,j)=f(i+1,j-1)+2。
當itring
[i]≠s
tring
[j]時,f(i,j)=max( f(i,j-1), f(i+1,j) )。
注意如果i+1=j並且s
tring[i]=string
[j]時,f(i,j)=f(i+1,j-1)+2=f(j,j-1)+2=2,這就是「當i>j時f(i,j)=0」的好處。
由於f(i,j)依賴i+1,所以迴圈計算的時候,第一維必須倒過來計算,從string.length-1到0。
最後,string的最長回文子串行長度為f(0, string.length-1)。
好了,由這個方法拓展,怎麼拓呢??設get(i,j)為獲取字串string[i:j]中間所有回文子串行的函式
(1)對於string[i:j]來說,若有string[i]==string[j],則get(i,j)由此幾部分組成-------string[i]、string[j]、get(i+1,j-1)、get(i,j-1)、get(i+1,j)、string[i]-string[j]、string[i]-get(i+1,j-1)-string[j](因為最兩頭已回文,故與
get(i+1,j-1)相同,是比get(i+1,j-1)長2個字元的回文子串行);
(2)若有string[i]!=string[j],則get(i,j)由此幾部分組成-------string[i]、string[j]、get(i+1,j-1)、get(i,j-1)、get(i+1,j);
(3)if(i==j)get(i,j)==1;
但是在(1)(2)中,
get(i,j-1)、get(i+1,j)
同時又包含
get(i+1,j-1),且
get(i,j-1)包含string[i],
get(i+1,j)包含string[j]。
因此,實際上,當
string[i]==string[j],則get(i,j)=get(i,j-1)+get(i+1,j)+1; 當
string[i]!=string[j],則
get(i,j)=get(i,j-1)+get(i+1,j)-
get(i+1,j-1);
動態規劃和分治思路是一樣的,只不過實現不一樣。
由分治法得到**:
#include
#include
#include
int lps_develope(char *str,int i,int j)//利用分治法,找出所有回文子串行的個數
int main()
} 使用動態規劃方法(由分治轉換)
#include
#include
#include
int main(void)
char str[30];
int scan_t,i=0,j=0,m=0,length=0,sum=0;
int str_m[25][25];
scanf("%d",&scan_t);
for(i=0; iscanf("%s",str);
length=strlen(str);
// sum=lps_develope(str,0,length-1);
memset(str_m,0,sizeof(str_m));
for(j=length-1; j>=0; j--)
{ //利用動態規劃法求解
str_m[j][j]=1;//由分治法思路轉換
for(m=j+1; mif(str[j]==str[m])
str_m[j][m]=1+str_m[j+1][m]+str_m[j][m-1];
else
str_m[j][m]=str_m[j+1][m]+str_m[j][m-1]-str_m[j+1][m-1];
if(i!=scan_t-1)
printf("case #%d: %d\n",i+1,str_m[0][length-1]);
else
printf("case #%d: %d",i+1,str_m[0][length-1]);
return 0;
返回所有的最長回文子串 O n
用馬拉車演算法將回文半徑p i 求出來,回文字串的長度就是p i 1,起始的下標就是 i p i 2,遍歷一次p i 陣列將所有最大長度的 字串存到vector就可以了。include using namespace std string solve string s,vector v vector...
字串 最長回文子串
最長回文子串 回文子串 即正著看和倒著看相同的子串,如 abcba yyxyy。由於此類題目為面試筆試常考題目,所以現在就來整理一下啦。1 暴力求解法 最直接的想法就是暴力求解,但是我們可以看到下面的 時間複雜度是o n 3 string findlongeststring string str 暴...
字串 最長回文子串
介紹一下幾個概念 就是從左往右和從右往左讀是一樣的。就如標語 我為人人,人人為我 子串,顧名思義,就是在原字串中的子集,就叫子串。串就是不能分割的,就是連在一起,這個要區別與子串行,子串行就是一段 一段的。列舉各個起點和終點,然後進行判斷該子串是否為回文,最後就是更新最長的回文串。列舉起點和終點 o...