1. 程式人生 > >HDU 1159 【DP之最長公共子序列】

HDU 1159 【DP之最長公共子序列】

類似於字典序比較的最長公共子序列,

只要找到狀態方程就比較好搞,

從角標1開始計算不會出錯,從0還是報錯了;

切防止對比溢位要在本來的基礎上+1計算;

言歸正傳:

DP型別都是狀態方程很重要;

假設兩個作對比,分別是s1,s2,則一定有 則dp[i][j] 就為s1前 i 個和s2前 j 個的公共子序列;

動態方程就是

				if(s1[i]==s2[j])
				{
					dp[i][j]=dp[i-1][j-1]+1;
				}
				else
				{
					if(dp[i][j-1]>dp[i-1][j])
					{
						dp[i][j]=dp[i][j-1];
					}
					else dp[i][j]=dp[i-1][j];
				}

AC程式碼就是:

#include <iostream>
#include <string.h>
#include <cstdio>
using namespace std ;
const int maxi = 1000;
int ma[maxi][maxi];
char s1[maxi],s2[maxi];
int main()
{
	while(scanf("%s%s",s1+1,s2+1)!=EOF)
	{
		int n1 = strlen(s1+1);
		int n2 = strlen(s2+1);
		for(int i = 0 ; i <=n1;i++)
		ma[i][0]=0;
		for(int j = 0 ; j<=n2;j++)
		ma[0][j]=0;
		
		for(int i = 1 ; i<=n1;i++)
		{
			for(int j = 1 ; j<=n2;j++)
			{
				if(s1[i]==s2[j])
				{
					ma[i][j]=ma[i-1][j-1]+1;
				}
				else
				{
					if(ma[i][j-1]>ma[i-1][j])
					{
						ma[i][j]=ma[i][j-1];
					}
					else ma[i][j]=ma[i-1][j];
				}
			}
		 } 
		 cout<<ma[n1][n2]<<endl;
	}
	return 0 ;
}

DP就是找狀態方程去證明,慢慢找,需要大量練習;