hdu3608最長回文子串

2021-07-10 15:01:10 字數 2417 閱讀 1605

首先做這個題目時候以為是動態規劃,可惜的是超時了。雖然超時了,但還是先說說動態規劃。設原串為s用dp[i,j]表示s[i...j]中最大回文字串的長度,則dp[i,j]的子問題可以劃分為dp[i+1,j],dp[i,j-1],以及dp[i+1,j-1].當然還需要乙個陣列flag[i,j]來記錄狀態。若flag[i,j]=1,則它表示在 s[i,j]中兩個端點字元s[i】與s[j] 是s[i..j]最長回文子串構成的部分,即s[i,j]就是乙個回文串。否則flag[i,j]=0表示s[i]和s[j]不同時是s[i..j]子串的構成部分。狀態轉移方程可以如下:

若flag[i ][j]==0 or s[i]!=s[j] ,dp[i,j]=max,若flag[i][j]==1 and s[i]==s[j] ,dp[i,j]=dp[i-1][j-1]+2.

具體處理時,不用開乙個很大的陣列,因為打表時候用到的只有那幾行,定義dp[3][max_size]即可,計算時採用取模運算,詳見**。很可惜,這是o(n^2)的演算法ac不了。

#include#includeusing namespace std;

#define max_size 110004

#define n 3

int dp[n][max_size];

bool flag[n][max_size];

char s[max_size];

int the_longest_palindrome();

int max(int a, int b)

int main()

return 0;

}int the_longest_palindrome()

dp[0][0] = 1;

for (l = 2; l <= l; l++)

else

} }return dp[0][l - 1];

}

下面用到的演算法參考博文:manacher演算法總結 - open 開發經驗庫

叫做manacher演算法。

定義p[i]表示以第i個字元為中心的最大回文串的半徑長度(包括第 i 個字元)。計算的時候從前向後掃瞄一遍,也就是說在計算p[i+k]的時候p[0...i+k-1]都是計算好了的。假設 i+p[i] 是在已經計算完的序列中能延伸到的最右端。我們下一步計算p[i+k],那麼點i+k必定包含在p[i]+i中,即為i+k<=i+p[i] => k<=p[i] ,由對稱性可知。下面的討論分為3個情況:

1)i-k位置的回文串完全包含在i位置的回文串內部,i-k回文串最左端位置為:i-k-p[i-k],而 i 回文串最左端為; i-p[i] 。這時候 i 回文串在i-k回文串左端的左端,即有 i-p[i]p[i]>k+p[i-k]. 對稱可知,i+k的回文串至少有 一段和i-k的回文串相同 。倘若i+k的回文串向兩邊延伸,勢必會得到 i-k 的串也會增長,從而i+k的串不可能再向兩邊延伸。故而有:

若p[i]>k+p[i-k] 則:

p[i+k]=p[i-k];

2) i-k位置的回文串左端 恰好與 i 位置的回文串左端重合。此時有i-k-p[i-k]=i-p[i] => p[i]=k+p[i-k].這個時候至少有 p[i+k]=p[i-k],但是此時i+k串向兩邊延伸是合法的,不會產生矛盾。故而有:

若p[i]=k+p[i-k]則:

p[i+k]=p[i-k];

while(s[i+k+p[i+k]]==s[i+k-p[i+k]]) p[i+k]++;

3)i-k位置的回文串最左端超過了 i 位置的回文串,即有 i-k-p[i-k]p[i]若 p[i]p[i+k]=p[i]-k;

以上三種情況綜合起來考慮就是:

p[i+k]=min ;

while(s[i+k+p[i+k]]==s[i+k-p[i+k]])   p[i+k]++;

具體處理的時候將長度為len的串每個字元和兩端都插上乙個字元『#』,或者其它串中沒有出現的字元。此時串長度變為2*len+1.

#includeusing namespace std;

char ch[110003 * 2];

int p[110003 * 2];

int min(int a, int b)

int main()

ch[0] = '#';

//----------------------------------------完成初始化插值

len = len * 2 + 1; //新陣列長度

i = k = 1;

maxlen = 2;

while (i + k < len)

else

k++; //更新k

} printf("%d\n", maxlen - 1);

} return 0;

}

HDU 3608 最長回文

problem description 給出乙個只由小寫英文本元a,b,c.y,z組成的字串s,求s中最長回文串的長度.回文就是正反讀都是一樣的字串,如aba,abba等 input 輸入有多組case,不超過120組,每組輸入為一行小寫英文本元a,b,c.y,z組成的字串s 兩組case之間由空行...

HDU 3068 最長回文 最長回文子串

和上一題一樣,不過這題只是要求最長回文子串的長度 在此採用了非常好用的manacher演算法 據說還是o n 的效率qaq 詳細用法參考了上篇部落格的參考資料,這兩天有空學習一下 source code pragma comment linker,stack 16777216 for c compi...

hdu 3068 最長回文子串O n

感覺這篇部落格寫的不錯 我就直接上 了。1 include2 include3 const int n 110010 4 using namespace std 5int len 6int p n 1 7 char s n str n 1 8 陣列p i 來記錄以字元str i 為中心的最長回文子串...