Trip
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3850 | Accepted: 1030 |
Description
Alice and Bob want to go on holiday. Each of them has planned a route, which is a list of cities to be visited in a given order. A route may contain a city more than once.
As they want to travel together, they have to agree on a common route. None wants to change the order of the cities on his or her route or add other cities. Therefore they have no choice but to remove some cities from the route. Of course the common route should be as long as possible.
There are exactly 26 cities in the region. Therefore they are encoded on the lists as lower case letters from 'a' to 'z'.
As they want to travel together, they have to agree on a common route. None wants to change the order of the cities on his or her route or add other cities. Therefore they have no choice but to remove some cities from the route. Of course the common route should be as long as possible.
There are exactly 26 cities in the region. Therefore they are encoded on the lists as lower case letters from 'a' to 'z'.
Input
The input consists of two lines; the first line is Alice's list, the second line is Bob's list.
Each list consists of 1 to 80 lower case letters with no spaces inbetween.
Each list consists of 1 to 80 lower case letters with no spaces inbetween.
Output
The output should contain all routes that meet the conditions described above, but no route should be listed more than once. Each route should be printed on a separate line. There is at least one such non-empty route, but never more than 1000 different ones. Output them in ascending order.
Sample Input
abcabcaa acbacba
Sample Output
ababa abaca abcba acaba acaca acbaa acbca
Source
题意:
求最长公共子序列,要求输出所有方案。
思路:
最长公共子序列好求,难点在输出方案。
用dp[i][j]表示处理到alice[i]和bob[j]时的最优解。如果alice[i]bob[j]不相等,dp[i][j]从dp[i-1][j], dp[j][i-1]中取较大的。相等,则dp[i-1][j-1]+1
先得到最优解,然后我们来输出所有方案。排序和去重都简单,用个set就行了。
首先我们预处理出alice串1~i的子串中,字符j+'a'最后一次出现的位置,存入pos1[i][j]。对bob串也做同样的处理。
然后我们进行递归。len1表示alice子串长度,len2表示bob子串长度,len表示公共串的子串长度。
枚举26个字母,找到他们在子串中最后出现的位置,如果我们发现dp[p1][p2] = len,那么说明这是一种可行的方案。并且这表示,这个字母会出现在这个方案的len位置。于是我们继续递归,去找(len1-1,len2-1,len-1)。直到len小于0了,说明现在当前跑出来的这个串跑完了,他是一个完整的方案,insert进set。如果在len到0之前,len1或者len2就已经小于0了,说明这个方案最后不可行了,也就不会insert,而会回溯。整个过程相当于是一个dfs。
WA了一次是因为输出了一下方案数的个数.....
1 //#include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<vector> 8 #include<map> 9 #include<set> 10 11 #define inf 0x3f3f3f3f 12 using namespace std; 13 typedef long long LL; 14 15 16 char alice[100], bob[100], tmp[100]; 17 int dp[100][100], pos1[100][100], pos2[100][100]; 18 set<string> ans; 19 int lena, lenb; 20 21 void solve(int len1, int len2, int len) 22 { 23 if(len <= 0){ 24 string str; 25 str = tmp + 1; 26 //memset(tmp, 0, sizeof(tmp)); 27 //cout<<str<<endl; 28 ans.insert(str); 29 return; 30 } 31 if(len1 > 0 && len2 > 0){ 32 for(int i = 0; i < 26; i++){ 33 int p1 = pos1[len1][i]; 34 int p2 = pos2[len2][i]; 35 if(dp[p1][p2] == len){ 36 tmp[len] = i + 'a'; 37 solve(p1 - 1, p2 - 1, len - 1); 38 } 39 } 40 } 41 42 } 43 44 int main() 45 { 46 while(scanf("%s%s", alice + 1, bob + 1) != EOF){ 47 lena = strlen(alice + 1); 48 lenb = strlen(bob + 1); 49 //ans.clear(); 50 51 for(int i = 0; i <= lena; i++){ 52 dp[i][0] = 0; 53 } 54 for(int j = 0; j <= lenb; j++){ 55 dp[0][j] = 0; 56 } 57 58 int tmpi = -1, tmpj = -1; 59 for(int i = 1; i <= lena; i++){ 60 for(int j = 1; j <= lenb; j++){ 61 dp[i][j] = max(dp[i][j], dp[i - 1][j]); 62 dp[i][j] = max(dp[i][j], dp[i][j - 1]); 63 if(alice[i] == bob[j]){ 64 dp[i][j] = dp[i - 1][j - 1] + 1; 65 } 66 } 67 } 68 69 memset(pos1, -1, sizeof(pos1)); 70 memset(pos2, -1, sizeof(pos2)); 71 for(int i = 1; i <= lena; i++){ 72 for(int j = 0; j < 26; j++){ 73 if(alice[i] == j +'a'){ 74 pos1[i][j] = i; 75 } 76 else{ 77 pos1[i][j] = pos1[i - 1][j]; 78 } 79 } 80 } 81 for(int i = 1; i <= lenb; i++){ 82 for(int j = 0; j < 26; j++){ 83 if(bob[i] == j + 'a'){ 84 pos2[i][j] = i; 85 } 86 else{ 87 pos2[i][j] = pos2[i - 1][j]; 88 } 89 } 90 } 91 92 //printf("%d ", dp[lena][lenb]); 93 memset(tmp, 0, sizeof(tmp)); 94 solve(lena, lenb, dp[lena][lenb]); 95 set<string>::iterator iter; 96 for(iter = ans.begin(); iter != ans.end(); iter++){ 97 cout<<*iter<<endl; 98 } 99 100 } 101 102 return 0; 103 }