1. 程式人生 > >演算法:動態規劃——區間模型之最少新增幾個字元使得字串變成迴文串

演算法:動態規劃——區間模型之最少新增幾個字元使得字串變成迴文串

題目:給定一個長度為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;
 
}