演算法:動態規劃——區間模型之最少新增幾個字元使得字串變成迴文串
阿新 • • 發佈:2019-01-08
題目:給定一個長度為n(n <= 1000)的字串A,求插入最少多少個字元使得它變成一個迴文串。
思路:
典型的動態規劃區間模型,區間模型的狀態表示一般為d[i][j],表示區間[i, j]上的最優解,然後通過狀態轉移計算出[i+1, j]或者[i, j+1]上的最優解,逐步擴大區間的範圍,最終求得[1, len]的最優解。
迴文串擁有很明顯的子結構特徵,即當字串X是一個迴文串時,在X兩邊各新增一個字元‘a’後,aXa仍然是一個迴文串,我們用d[i][j]來表示A[i…j]這個子串變成迴文串所需要新增的最少的字元數,那麼對於A[i] == A[j]的情況,很明顯有 d[i][j] = d[i+1][j-1] (這裡需要明確一點,當i+1 > j-1時也是有意義的,它代表的是空串,空串也是一個迴文串,所以這種情況下d[i+1][j-1] = 0);當A[i] != A[j]時,我們將它變成更小的子問題求解,我們有兩種決策:
1、在A[j]後面新增一個字元A[i];
2、在A[i]前面新增一個字元A[j];
根據兩種決策列出狀態轉移方程為:
d[i][j] = min{ d[i+1][j], d[i][j-1] } + 1; (每次狀態轉移,區間長度增加1)
空間複雜度O(n^2),時間複雜度O(n^2),
程式碼:#include<iostream> #include<string> using namespace std; int main() { string str; cin>>str; int len = str.length(); int**vec = new int*[len];//vec[i][j]表示i到j之間的字串要成為迴文串所需要增加的最小字元數 for (int i=0;i<len;i++) { vec[i]=new int[len](); } int i,j,k; for (k=2;k<=len;k++)//k表示相隔的長度 { for (i=0;i+k-1<len;i++) { j=i+k-1; if (str[i]==str[j]) { vec[i][j]=vec[i+1][j-1]; } else { vec[i][j]=min(vec[i+1][j],vec[i][j-1])+1;//在前面或者後面新增一個字元 } } } cout<<vec[0][len-1]; return 0; }