http://acm.hdu.edu.cn/showproblem.php?pid=1503
题意:给两个字符串,组成一个长度尽可能小的字符串,它包含上述两个字符串,且原字符串中的字符在该串中的相对位置不变。
思路:想到了最长公共子序列,但需要找到最长公共子序列是哪些。可以拿个二维数组记录第一个字符串i和第二个字符串j处的状态。然后根据状态递归,分别用一个数组记录公共字符在两个字符串中的位置。这样就找到了最长公共子序列中的字符。
然后按要求输出。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; char s1[110],s2[110],s[210]; int pre[110][110];//pre[i][j]记录到达第一个字符串i与第二个字符串j的状态。 int len1,len2; int dp[110][110]; int ind1[110],ind2[110];//记录公共字符在两字符串中的位置 int cnt;//记录公共子序列中字符的个数 //求最长公共子序列,并记录状态 void get_len() { memset(dp,0,sizeof(dp)); for(int i = 1; i <= len1; i++) { for(int j = 1; j <= len2; j++) { if(s1[i-1] == s2[j-1]) { dp[i][j] = dp[i-1][j-1]+1; pre[i][j] = 0; } else { if(dp[i-1][j] > dp[i][j-1]) { pre[i][j] = 1; dp[i][j] = dp[i-1][j]; } else { pre[i][j] = 2; dp[i][j] = dp[i][j-1]; } } } } } //递归查找公共子序列中每个字符在两字符串中所对应下标 void dfs(int i, int j) { if(i == 0 || j == 0) return; if(pre[i][j] == 1) dfs(i-1,j); else if(pre[i][j] == 2) dfs(i,j-1); else { dfs(i-1,j-1); ind1[++cnt] = i-1; ind2[cnt] = j-1; } } int main() { while(~scanf("%s %s",s1,s2)) { len1 = strlen(s1); len2 = strlen(s2); get_len(); cnt = 0; dfs(len1,len2); int count = 0; int j = 0,k = 0; for(int i = 1; i <= cnt; i++) {//将公共字符之前的字符存在s中 for(; j <= ind1[i]-1; j++) s[count++] = s1[j]; for(; k <= ind2[i]-1; k++) s[count++] = s2[k]; s[count++] = s1[j]; j++; k++; } while(s1[j] != ‘\0‘) s[count++] = s1[j++]; while(s2[k] != ‘\0‘) s[count++] = s2[k++]; s[count] = ‘\0‘; printf("%s\n",s); } return 0; }
hdu 1503 Advanced Fruits(最长公共子序列变形),布布扣,bubuko.com
hdu 1503 Advanced Fruits(最长公共子序列变形)
原文:http://blog.csdn.net/u013081425/article/details/20565217