題目來自nyist第37題,如下:
描述
所謂回文字符串,就是一個字符串,從左到右讀和從右到左讀是完全一樣的,比如"aba"。當然,我們給你的問題不會再簡單到判斷一個字符串是不是回文字符串。現在要求你,給你一個字符串,可在任意位置添加字符,最少再添加幾個字符,可以使這個字符串成為回文字符串。輸入第一行給出整數N(0<N<100)接下來的N行,每行一個字符串,每個字符串長度不超過1000.輸出每行輸出所需添加的最少字符數
DP解法,先找遞推式,要求ai,ai+1,ai+2....aj序列的解,有兩種情況,第一是ai == aj,則轉換為求ai+1,ai+2 ... aj-1序列的解;第二是ai != aj,此時可能的最小解是在左邊添上一個aj-1,這樣便轉換為第一種情況,或者在右邊添上一個ai+1,也轉換為第一種情況,而最終父問題的解就取自直接子問題以及第二種情況中兩個子問題中的最小解。
由此只要求父問題需要先求子問題,自下而上遞推;由于要求的子問題是1、2;2、3;3、4....n-1、n以及1、2、3;2、3、4;......n-2、n-1、n(數字代表字符串的下標)等等,即需要一個n*(n-1)/2大小的數組來存放自下而上的計算結果。本題中采用二維數組,其中dp[i][j]表示從第i個字符到第j個字符所組成的序列的解。
代碼如下:
#include <stdio.h>#include <string.h>#include <stdlib.h>int dp[1000][1000+2];int main(){ int N,i,j,gap,len; char s[1000+5]; scanf("%d",&N); while(N--) { memset(dp,0,sizeof(dp)); scanf("%s",s); len = strlen(s); for(i = 0;i < len;i++) dp[i][i] = dp[i][i-1] = 0; for(gap = 1;gap < len;gap++) //表示當前考慮的序列長度-1 for(i = 0;i < len-gap;i++) //表示當前考慮的序列的起始字符下標 { j = i + gap; //end dp[i][j] = 1000;//任意的大值即可 if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1]; dp[i][j] = dp[i][j] > (dp[i+1][j]+1) ? (dp[i+1][j]+1) : dp[i][j]; dp[i][j] = dp[i][j] > (dp[i][j-1]+1) ? (dp[i][j-1]+1) : dp[i][j]; } PRintf("%d/n",dp[0][len-1]); }}動規的題目代碼量不算很大,但是個人感覺還是較為難想,還需要積累聯系。
新聞熱點
疑難解答