题意:给出两个字符串,求能满足子串(可以不连续)中包含给出的两个字符串的最短字符串.
思路:本质上就是LCS问题,做法是先找出两个串的LCS,并记录其位置
设dp[i][j]为A串以第i个字符结尾B串以第j个字符结尾的LCS, 用path数组来记录路径,
如果A[i] == B[j] 那么dp[i][j] = dp[i - 1][j - 1].
否则 dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) .
用两个数组pos1, pos2分别代表LCS在各自串中的位置.
那么不是LCS的字符就要按照一定的顺序打印,详细的看代码吧
#include <cstdio> #include <string> #include <iostream> #include <memory.h> using namespace std; const int MAX = 128; int dp[MAX][MAX]; int pos1[MAX], pos2[MAX], cnt; char path[MAX][MAX]; char f1[MAX], f2[MAX]; void traverse(int i, int j){ if(i == 0 || j == 0)return; if(path[i][j] == 0){ traverse(i - 1, j - 1); pos1[cnt] = i; pos2[cnt++] = j; }else if(path[i][j] == 1){ traverse(i - 1, j); }else{ traverse(i, j - 1); } } int main(int argc, char const *argv[]){ while(scanf("%s%s", f1 + 1, f2 + 1) == 2){ memset(dp, 0, sizeof(dp)); int len1 = strlen(f1 + 1), len2 = strlen(f2 + 1); for(int i = 1; i <= len1; ++i){ for(int j = 1; j <= len2; ++j){ if(f1[i] == f2[j]){ dp[i][j] = dp[i - 1][j - 1] + 1; path[i][j] = 0; }else if(dp[i - 1][j] > dp[i][j - 1]){ dp[i][j] = dp[i - 1][j]; path[i][j] = 1; }else{ dp[i][j] = dp[i][j - 1]; path[i][j] = 2; } } } cnt = 1; traverse(len1, len2); pos1[cnt] = len1 + 1; pos2[cnt++] = len2 + 1; for(int i = 1; i < cnt; ++i){ for(int j = pos1[i - 1] + 1; j < pos1[i]; ++j){ printf("%c", f1[j]); } for(int j = pos2[i - 1] + 1; j < pos2[i]; ++j){ printf("%c", f2[j]); } if(i != cnt - 1) printf("%c", f1[pos1[i]]); } printf("\n"); } return 0; }
ZOJ 1953 Advanced Fruits(LCS),布布扣,bubuko.com
原文:http://blog.csdn.net/zxjcarrot/article/details/23130253