1. 程式人生 > >動態規劃之最長01子序列問題

動態規劃之最長01子序列問題

 問題描述

  • 現在有兩個字串已知
  • 要求的他們最長的公共子序列長度
  • 例如csdnblog和belong的最長公共子序列是4,由於它們都含有blog這一個子序列

 解題思路與演算法思想

既然使用動態規劃演算法,那麼演算法的核心就是將問題分佈
	這一點和數學歸納法有點相似
假設含有字串xc長度為a
有字串y長度為b
現在在比較x的前a1位和y的前b1位置的最長公共子序列
	那麼我們需要假設已知之前的所有狀態,如圖:

在這裡插入圖片描述
 程式模型的建立

  • 先將資料輸入
  • 建立轉移方程:
如果當前的兩個字元相同
	那麼加一
如果不同
	在其他狀態之中選擇一個比較大的
  • 之後通過遞迴+記憶的方式計算出匹配的最大字串
  • 最後將匹配的個數輸出

 資料結構的選用
選用string去儲存這兩個字串

 程式設計流程
輸入資料
進行計算
輸出結果

 程式設計偽碼演算法

	if((c<0)||(d<0))
	{
		return 0 ;
	}
	
	if(bb[c][d]!=-1)
	{
		return bb[c][d] ;
	}
	
	
	if(a[c] == b[d] )
	{
		bb[c][d] = find_num(a,b,c-1,d-1)+1 ;
		return bb[c][d]  ;
	}
	else
	{
		bb[c][d] = max(find_num(a,b,c-1,d),find_num(a,b,c,d-1)) ;
		return bb[c][d]  ;
	
	}

 源程式編碼清單

#include<iostream>
#include<string>
#include<vector>
using namespace std ;
int find_num(string a ,string b ,int c ,int d) ;
vector< vector<int> > bb ;
int main(void)
{
	string a ;
	string b ;
	vector<int>aa ;
	
	
	cin>>a ;
	cin>>b ;
	for(int i = 0 ;i<b.size() ;i++)
	{
		aa.push_back(-1) ;
	}
	for(int i = 0 ;i<a.size() ;i++)
	{
		bb.push_back(aa) ;
	}
	printf("%d",find_num(a,b,a.size()-1,b.size()-1)) ;
}
int find_num(string a ,string b ,int c ,int d) 
{
	if((c<0)||(d<0))
	{
		return 0 ;
	}
	
	if(bb[c][d]!=-1)
	{
		return bb[c][d] ;
	}
	
	
	if(a[c] == b[d] )
	{
		bb[c][d] = find_num(a,b,c-1,d-1)+1 ;
		return bb[c][d]  ;
	}
	else
	{
		bb[c][d] = max(find_num(a,b,c-1,d),find_num(a,b,c,d-1)) ;
		return bb[c][d]  ;
	
	}
}

 程式輸入、輸出

輸入:
csdnblog
belong
輸出:
4

輸入輸出檔案,或程式執行結果截圖
在這裡插入圖片描述
 時間與空間複雜度分析
時間複雜度是n^2
 程式使用說明

 總結與完善