一個比較簡單的最長公共子序列.
題目大意: 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;
}