標籤:
Compromise
題目:
題目大意:
這裡有兩篇短文,每篇短文有若干個單詞,求這兩篇短文中的最長公用子序列,並將其輸出來!
沒篇短文輸入 為 “#” 時,結束該篇短文的輸入。
這道題是多組測試資料,如果唯寫一組,那麼就會 WA,我因為這就被 WA 了一次!
最長公用子序列的解法,就不多說了,基本上所有的演算法書上都有介紹講解。
這道題,題意和解法我認為都不是痛點,我個人認為痛點是在最長公用子序列的儲存記錄上。
對於最長公用子序列的記錄儲存上,我用了 C++ 的 STL 中的string 來記錄儲存,string 的好處在於可以直接進行字串的相加,因此就比較方便多了,對於輸出資料的儲存,我用了 vector 容器,這樣讀取的時候就比較方便,並且裡面儲存 string 類型的變數,對於後面的解答方便多了!
附上代碼:
#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <vector>#define INF 0x3f3f3f3fusing namespace std;int main(){vector <string> str;vector <string> str1;string str2;int n = 0,m = 0;while(cin >> str2) // 執行多組測試資料,這題是多組測試資料,寫一組結果是錯的{str.clear();str1.clear();n = 0;m = 0;if(str2 != "#") // 判斷第一篇文章的第一個輸入的是不是 # 如果不是,繼續輸入,反之,輸入第二篇文章的資料{n++;str.push_back(str2); while(cin >> str2 && str2 != "#") { n++;str.push_back(str2); }}while(cin >> str2 && str2 != "#"){m++;str1.push_back(str2);}int dp[110][110] = {0};string ans[110][110]; // ans[i][j] 表示到達第一個到達 i 第二個到達 j 時的最長公用子序列vector <string> :: iterator it1; // 定義迭代器vector <string> :: iterator it2; // 同上int i = 0,j;for(it1 = str.begin();it1 != str.end();it1++,i++) // 兩層迴圈 , 動態規劃 解決最長公用子序列問題{j = 0;for(it2 = str1.begin();it2 != str1.end();it2++,j++){if(*it1 == *it2) // 如果單詞相同 進行 加 操作{dp[i + 1][j + 1] = dp[i][j] + 1;string a;if(!ans[i][j].empty())a += ' '; // ans 不為空白,那麼說明不是第一個,那麼與前一個單詞之間需要有一個空格a += *it1; ans[i + 1][j + 1] = ans[i][j] + a; // 將單詞加上面}else // 不相同的時候進行選擇,賦值{dp[i + 1][j + 1] = max(dp[i][j + 1],dp[i + 1][j]);ans[i + 1][j + 1] = dp[i][j + 1] > dp[i + 1][j] ? ans[i][j + 1] : ans[i + 1][j];}}}cout << ans[n][m] << endl; 輸出結果}return 0;}
POJ2250 & UVA 531 Compromise(字串、 最長公用子序列)