本文主要是介绍Coincidence (九度教程第98题) 最长公共子序列(LCS) 动态规划,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Find a longest common subsequence of two strings.
输入描述:
First and second line of each input case contain two strings of lowercase character a…z. There are no spaces before, inside or after the strings. Lengths of strings do not exceed 100.
输出描述:
For each case, output k – the length of a longest common subsequence in one line.
示例1
输入
abcd
cxbydz
输出
2
题目大意:
求出两个字符串的最长公共子串长度,典型的最长公共子序列问题。
解题思路:动态规划
与求最长递增子序列一样,我们首先将原问题分割成一些子问题,我们用
dp[ i ][ j ]表示 S1 中前 i 个字符与 S2 中前 j 个字符分别组成的两个前缀字符串的最
长公共子串长度。显然的,当 i、j 较小时我们可以直接得出答案,如 dp[ 0 ][ j ]必
等于 0。那么,假设我们已经求得 dp[ i ][ j ](0<=i<x || 0<=j<y)的所有值,考虑如何由
这些值继而推得 dp[x][y],求得 S1 前 x 个字符组成的前缀子串和 S2 前 y 个字符
组成的前缀子串的最长公共子序列长度。
若 S1[x] = =S2[y],即 S1 中的第 x 个字符和 S2 中的第 y 个字符相同,同时由于他们都是各自前缀子串的最后一个字符,那么必存在一个最长公共子串以 S1[x]或 S2[y]结尾,其它部分等价于 S1 中前 x-1个字符和S2中前y-1个字符的最长公共子串。所以这个子串的长度比dp[x-1][y-1]又增加 1,即 dp[x][y] = dp[x-1][y-1] + 1。
相反的,若 S1[x] != S2[y],此时其最长公共子串长度为 S1 中前 x-1 个字符和 S2 中前 y 个字符的最长公共子串长度与S1 中前 x 个字符和 S2 中前 y-1 个字符的最长公共子串长度的较大者,即在两种情况下得到的最长公共子串都不会因为其中一个字符串又增加了一个字符长度发生改变。综上所述,dp[x][y] = max{dp[x-1][y],dp[x][y-1]}。
综上所述,最长公共子序列问题的递推条件:
//字符串s1长度为n, 字符串s2长度为m
//dp[i][j]表示s1中前i个字符与s2中前j个字符分别组成的两个前缀字符串的最长公共子串长度
//dp[0][j]=0 0<=j<=m
//dp[i][0]=0 0<=i<=n
//dp[n][m]中保存的值即为两个原始字符串的最长公共子序列长度
if(s1[i]==s2[j]){ dp[i][j] = dp[i-1][j-1] + 1;}
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
AC代码
//最长公共子序列问题
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;int dp[101][101];
char s1[101], s2[101];
int main() {cin >> s1;cin >> s2;int a = strlen(s1);int b = strlen(s2);for (int i = 0; i <= a; i++) { dp[i][0] = 0; }for (int i = 0; i <= b; i++) { dp[0][i] = 0; }for (int i = 1; i <= a; i++) {for (int j = 1; j <= b; j++) {if (s1[i-1] == s2[j-1]) dp[i][j] = dp[i - 1][j - 1] + 1;else dp[i][j] = max( dp[i][j - 1], dp[i - 1][j] );}}cout << dp[a][b] << endl;//system("pause");return 0;
}
这篇关于Coincidence (九度教程第98题) 最长公共子序列(LCS) 动态规划的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!