题意:给定两个字符串,让你求一个最短的字符串,并且这个字符串包含给定的两个。
析:看到这个题,我知道是DP,但是,不会啊。。。完全没有思路么,我就是个DP渣渣,一直不会做DP。
最后还是参考了一下题解,主要是这样的,要想最短,就必须让两个字符串重复的最多,也就是LCS,
然后把剩下的不相同的字符再给补上,说起来容易,实现起来,难!反正对我来说是难。
然后根据LCS的原理,我们对这个两字符串,进行标记,什么意思呢,就是说,如果某个字符是公共字符,
等到输出时,我们只输出一次,而对于不是公共的,我们再分别输出,不过也要把握顺序,保证不会颠倒,
所以在这我们是用递归输出字符串,从最后递归到最前面,然后依次输出。
代码如下:
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 100 + 10; const int up = 2; const int down = 3; char s1[maxn], s2[maxn]; int mark[maxn][maxn], d[maxn][maxn]; void print(int i, int j){//递归输出 if(!i && !j) return ; if(1 == mark[i][j]){ print(i-1, j-1); printf("%c", s1[i]); } else if(up == mark[i][j]){//输出上面的 print(i-1, j); printf("%c", s1[i]); } else if(down == mark[i][j]){//输出下面的 print(i, j-1); printf("%c", s2[j]); } else if(!i && j){//第一串到起点了 print(i, j-1); printf("%c", s2[j]); } else if(i && !j){//第二串到起点了 print(i-1, j); printf("%c", s1[i]); } } int main(){ // freopen("in.txt", "r", stdin); while(~scanf("%s %s", s1+1, s2+1)){ int len1 = strlen(s1+1); int len2 = strlen(s2+1); memset(d, 0, sizeof(d)); memset(mark, 0, sizeof(mark)); for(int i = 1; i <= len1; ++i) for(int j = 1; j <= len2; ++j) if(s1[i] == s2[j]){ d[i][j] = d[i-1][j-1] + 1; mark[i][j] = 1; } else if(d[i-1][j] >= d[i][j-1]){ d[i][j] = d[i-1][j]; mark[i][j] = up; }//表示要输出上面的一个 else{ d[i][j] = d[i][j-1]; mark[i][j] = down; }//表示要输出下面的一个 print(len1, len2); printf(" "); } return 0; }