POJ 2250 - Compromise
http://poj.org/problem?id=2250
概要
2つの単語の列が与えられるので,それらの最長共通部分列を答える.
制約
- 単語は小文字のアルファベットのみからなる
- 単語の長さは 30 以下
- 単語の数は 100 個以下
解法
LCS の DP + 経路復元.
poj/2250.cc1 #include <iostream> 2 #include <vector> 3 #include <map> 4 using namespace std; 5 6 struct renamer 7 { 8 map<string,int> m; 9 vector<string> v; 10 int encode(const string& s) 11 { 12 map<string,int>::const_iterator it = m.find(s); 13 if (it == m.end()) { 14 const int id = m.size(); 15 m.insert(make_pair(s, id)); 16 v.push_back(s); 17 return id; 18 } else { 19 return it->second; 20 } 21 } 22 string decode(int id) const { return v[id]; } 23 }; 24 25 int main() 26 { 27 ios::sync_with_stdio(false); 28 string s; 29 while (cin >> s) { 30 vector<int> xs, ys; 31 renamer r; 32 xs.push_back(r.encode(s)); 33 while (cin >> s && s != "#") { 34 xs.push_back(r.encode(s)); 35 } 36 while (cin >> s && s != "#") { 37 ys.push_back(r.encode(s)); 38 } 39 40 const int N = xs.size(), M = ys.size(); 41 vector<vector<int> > lcs(N+1, vector<int>(M+1, 0)); 42 vector<vector<pair<int,int> > > prev(N+1, vector<pair<int,int> >(M+1, make_pair(-1, -1))); 43 for (int i = 1; i <= N; i++) { 44 for (int j = 1; j <= M; j++) { 45 int t = lcs[i-1][j-1] + (xs[i-1] == ys[j-1]); 46 lcs[i][j] = max(t, max(lcs[i-1][j], lcs[i][j-1])); 47 if (lcs[i][j] == t) { 48 prev[i][j] = make_pair(i-1, j-1); 49 } else if (lcs[i][j] == lcs[i-1][j]) { 50 prev[i][j] = make_pair(i-1, j); 51 } else { 52 prev[i][j] = make_pair(i, j-1); 53 } 54 } 55 } 56 57 vector<int> seq; 58 for (int i = N, j = M;;) { 59 const int k = prev[i][j].first; 60 const int l = prev[i][j].second; 61 if (k == -1 || l == -1) { 62 break; 63 } 64 if (k+1 == i && l+1 == j && lcs[k][l]+1 == lcs[i][j]) { 65 seq.push_back(xs[i-1]); 66 } 67 i = k; 68 j = l; 69 } 70 for (vector<int>::const_reverse_iterator it = seq.rbegin(); it != seq.rend(); ++it) { 71 if (it != seq.rbegin()) { 72 cout << ' '; 73 } 74 cout << r.decode(*it); 75 } 76 cout << endl; 77 } 78 return 0; 79 }