1. 程式人生 > >POJ 1159 Palindrome 最大公共子序列+滾動陣列

POJ 1159 Palindrome 最大公共子序列+滾動陣列

題目描述:

A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a program which, given a string, determines the minimal number of characters to be inserted into the string in order to obtain a palindrome. 

As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome. 
Input Your program is to read from standard input. The first line contains one integer: the length of the input string N, 3 <= N <= 5000. The second line contains one string with length N. The string is formed from uppercase letters from 'A' to 'Z', lowercase letters from 'a' to 'z' and digits from '0' to '9'. Uppercase and lowercase letters are to be considered distinct. Output Your program is to write to standard output. The first line contains one integer, which is the desired minimal number. Sample Input
5
Ab3bd
Sample Output
2

         題目意思是,把給定的字串變成迴文字串,求最少需要新增的字元數。

這題要利用最大公共子序列。一個字串和它倒過來的字串的最大公共

子序列,在這個上面新增字元就可以做到最少,使它成為迴文字串。

假設兩個兩個字串互為逆, s1 , s2 ;

         如果 s1 當前的字元和 s2 當前的字元相同,即 s1[i] == s2[j] , 那麼 s1的一段

 s1[ 0 , 1 ...i ] 和 s2 當前的一段  s2[ 0 , 1 ....j ] 的最長公共子序列就是

  s1[0,1,....i-1] 和 s2[0,1,...j-1] 最大公共子序列的基礎上+1,也就是添加了 s1[i] 和 s2[j] 。

        如果不相同, s1 當前和 s2 當前最大公共子序列的長度不會增加,等效於

不新增 s1[i] 或者不新增 s2[j] ,取其中的更大者。

          寫出狀態變化:

如果 s1[i] == s2[j] ,  dp[i][j] = dp[i-1][j-1]+1 ;

否則 dp[i][j] = max( dp[i-1][j] , dp[i][j-1] ) ;

還要利用到滾動陣列,因為當前的狀態只和前一個狀態有關,不然記憶體過不去。

如有錯誤,敬請指正。

程式碼:

#include <stdio.h>
#define max( a , b ) ( a > b ? a : b )
char s1[5005] , s2[5005] ;
int dp[2][5005] ;

int main(){
	int n , i = 1 , j = 1 ;
	scanf( "%d%s" , &n , s1+1 ) ;
	for( i = 1 ; i <= n ; ++i ) s2[i] = s1[n-i+1] ;
	for( i = 1 ; i <= n ; ++i )
		for( j = 1 ; j <= n ; ++j )
			dp[i&1][j] = s1[i] == s2[j] ? dp[(i-1)&1][j-1]+1 : max( dp[(i-1)&1][j] , dp[i&1][j-1] ) ;
	printf( "%d\n" , n-dp[n&1][n] ) ;
	return 0 ;
}