pku_2250_Compromise

一個比較簡單的最長公共子序列.

題目大意:  http://poj.org/problem?id=2250

給出兩段文字(以#號結束),求其中一樣的單詞的最大公共子序列,並記錄結果.

需要注意的是,有多組數據,需要判斷.還有就是 可以有一樣的單詞~因爲這個wa了一次.

解題思路:

1.因爲只有100個單詞,將每個單詞編號,這樣求lcs時候就對編號求就可以,不用比較每個字符串了.

        具體實現用map<string,int>  + vector<string> ;

2.在求lcs時候紀錄路徑,這時紀錄的路徑是逆向的,輸出到一個棧裏,輸出回來.

lcs的代碼就不用說了~

源代碼:

#include <myhead.h>

const int N=210;
const int bx3[4]={0,-1,-1, 0};
const int by3[4]={0,-1, 0,-1};
int a[N],b[N];
int dp[N][N],path[N][N];
vector<string> va;
map<string,int> ma;

bool getData(int *t) {
	//對每個單詞編號,從一開始.
	int m=1;
	string st;
	while(1) {
		if(cin.eof())
			return false;
		cin>>st;
		if(st==va[0])
			break;
		if(ma[st]==0) {
			ma[st]=va.size();
			va.push_back(st);
		}
		t[m]=ma[st];
		m+=1;
	}
	t[0]=m;
	return true;
}

bool init() {
	//初始化
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(dp,0,sizeof(dp));
	memset(path,0,sizeof(path));
	va.clear();
	ma.clear();
	va.push_back("#");
	return (getData(a)&&getData(b));
}

inline void inc(int &x,int &y,const int &t) {
	x+=bx3[t];
	y+=by3[t];
}

void work() {
	//求最大公共子序列
	for(int i=1;i<a[0];++i) {
		for(int j=1;j<b[0];++j) {
			if(a[i]==b[j]) {
				path[i][j]=1;
				dp[i][j]=dp[i-1][j-1]+1;
			} else {
				if(dp[i-1][j]>dp[i][j-1]) {
					path[i][j]=2;
					dp[i][j]=dp[i-1][j];
				} else {
					path[i][j]=3;
					dp[i][j]=dp[i][j-1];
				}
			}
		}
	}
	//往回找結果並輸出.
	int x=a[0]-1;
	int y=b[0]-1;
	bool make[N];
	memset(make,0,sizeof(make));
	stack<string> sa;
	while(path[x][y]) {
		int t=path[x][y];
		if(!make[a[x]]&&t==1) {
			sa.push(va[a[x]]);
		}
		inc(x,y,t);
	}
	while(!sa.empty()) {
		cout<<sa.top();
		sa.pop();
		if(!sa.empty()) cout<<" ";
	}
	cout<<endl;
}

int main() {
	while(init()) {
		work();
	}
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章