题意:
给出两个字符串,求出最长的公共子序列大小。
思路:
算是最经典的LCS问题吧。
设 \(X=(x_1,x_2,.....x_n) 和 Y=(y_1,y_2,.....y_m)\) 是两个序列,将 X 和 Y 的最长公共子序列记为\(lcs(X,Y)\) ,找出\(lcs(X,Y)\)就是一个最优问题
然后我们需要将其分解成子问题并求出子问题的最优解: (寻找子问题来推出当前问题,正是寻找状态转移方程最重要的一步)
1)如果 \(x_n=y_m\),即X的最后一个元素与Y的最后一个元素相同,这说明该元素一定位于公共子序列中。因此,现在只需要找:\(lcs(X_{n-1},Y_{m-1})\)
\(lcs(X_{n-1},Y_{m-1})\)就是原问题的一个子问题
2)如果\(x_n != y_m\)就往回递归寻找两个子问题:\(lcs(X_{n-1},Y{m}) 和 lcs(X_{n},Y_{m-1})\)
\(lcs(X_{n-1},Y_m)\)表示:最长公共序列可以在\((x_1,x_2,....x_{n-1}) 和 (y_1,y_2,...y_n)\)中找
\(lcs(X_n,Y_{m-1})\)表示:最长公共序列可以在\((x_1,x_2,....x_n) 和 (y_1,y_2,...y_{n-1})\)中找
最后就可以得到下面的 递推(递归)公式 :因此递推求解即可
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(0); cin.tie(0); #define accept 0 #define mp make_pair using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 0x3f3f3f3f; const int maxn = 1e3+7; const int maxm = 1e6+7; const int mod = 1e9+7; int dp[maxn][maxn]; char a[maxn],b[maxn]; int main(){ while(~scanf("%s%s",a,b)){ memset(dp,0,sizeof(dp)); int lena = strlen(a); int lenb = strlen(b); for(int i=1;i<=lena;i++){ for(int j=1;j<=lenb;j++){ if(a[i-1]==b[j-1]){ dp[i][j] = dp[i-1][j-1]+1; } else{ dp[i][j] = max(dp[i-1][j],dp[i][j-1]); } } } printf("%d\n",dp[lena][lenb]); } }