關於在字串中獲得所有的回文子串行的數量

2021-07-25 23:25:16 字數 2715 閱讀 7484

在這裡,我就把用到的所有知識、我的思路和一些查到的資料分享給大家。

方法一、(台灣的那個研究生的思路)

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...