标签:namespace c++ class nod ++ 链接 路径 define pac
题目链接:https://vjudge.net/contest/225715#problem/B
转载于>>>
题目大意:
给出两个序列,要求输出它们的最长公共子序列。
解题思路:
最长公共子序列模板题~
我们用dp[i][j]表示到a串第i个字符, b串第j个字符的最大匹配字符数,那么状态转移方程为:
dp[i][j]=dp[i-1][j-1]+1 a[i]==b[j] dp[i][j]=max(dp[i][j-1], dp[i-1][j]) a[i]!=b[j]
我们可以这样理解:dp[i][j]表示第a串前i个字符与b串前j个字符的最大匹配数,dp[i-1][j-1]表示a字符前i-1个字符与b串前j-1个字符的最大匹配数
如果a[i]=b[j],那么很明显dp[i][j]=dp[i-1][j-1]+1;
若a[i]!=b[j],我们假设a, b的最大匹配串为c,显然a[i], b[j]不能同时作为c的最后一个字符,那么最优匹配情况即为a[i]为c的最后一个字符或者b[j]为c的最后一个字符(这点不大好理解),即
dp[i][j]=dp[i][j-1] a[i]是c的最后一个字符即匹配的末尾字符
dp[i][j]=dp[i-1][j] b[j]是c的最后一个字符即匹配的末尾字符 (其实当a[i], b[j]都不是c的最后一个字符时即a[i], b[j]都不匹配时dp[i][j]=dp[i-1][j-1])
又dp要取最大值 ,即dp[i][j]=max(dp[i][j-1], dp[i-1][j])
题目还要求要输出一个最优匹配串,这个我们用vis[][]数组在dp过程中记录一下路径就好啦~
非递归输出路径
#include <bits/stdc++.h> using namespace std; #define MAXN 1010 int dp[MAXN][MAXN]; int vis[MAXN][MAXN]; string stra, strb; char output[MAXN]; int cur = 0; void getlcs(int i, int j) { while (i>0&&j>0) //逆推取出vis中保存的路径 { if (vis[i][j]==1) { output[cur++] = stra[i - 1]; i--; j--; } else if (vis[i][j] == 2) { j--; } else { i--; } } } int main() { cin >> stra >> strb; int lena = stra.length(); int lenb = strb.length(); for (int i = 1; i <= lena; i++){ for (int j = 1; j <= lenb; j++) { if (stra[i - 1] == strb[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; vis[i][j] = 1; //vis数组标记路径 } else { if (dp[i - 1][j] < dp[i][j - 1]) { dp[i][j] = dp[i][j - 1]; vis[i][j] = 2; } else { dp[i][j] = dp[i - 1][j]; vis[i][j] = 3; } } } } getlcs(lena, lenb); for (int i = cur - 1; i >= 0; i--) //逆向输出 printf("%c", output[i]); cout << endl; return 0; }
递归输出路径
#include <bits/stdc++.h> using namespace std; #define MAXN 1010 int dp[MAXN][MAXN]; int vis[MAXN][MAXN]; string stra, strb; void getlcs(int i, int j) { //**输出路径 if (!i || !j) { //因为i-1要>=0 return; } if (vis[i][j] == 1) { getlcs(i - 1, j - 1); printf("%c", stra[i - 1]); } else if (vis[i][j] == 2) { getlcs(i, j - 1); } else { getlcs(i - 1, j); } } int main() { cin >> stra >> strb; int lena = stra.length(); int lenb = strb.length(); for (int i = 1; i <= lena; i++){ for (int j = 1; j <= lenb; j++) { if (stra[i - 1] == strb[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; vis[i][j] = 1; //vis数组标记路径 } else { if (dp[i - 1][j] < dp[i][j - 1]) { dp[i][j] = dp[i][j - 1]; vis[i][j] = 2; } else { dp[i][j] = dp[i - 1][j]; vis[i][j] = 3; } } } } getlcs(lena, lenb); cout << endl; return 0; }
2018-05-18
标签:namespace c++ class nod ++ 链接 路径 define pac
原文地址:https://www.cnblogs.com/00isok/p/9058040.html