POJ 1458 Common Subsequence(最长公共子序列)__动态规划

来源:互联网 发布:巨人网络借壳上市分析 编辑:程序博客网 时间:2024/06/07 06:33

描述

我们称序列 Z = < z1, z2, …, zk >是序列X = < x1, x2, …, xm >的子序列当且仅当存在严格上升的序列< i1, i2, …, ik >,使得对j = 1, 2, … ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b, c, f, b, c >的子序列。
现在给出两个序列X 和Y,你的任务是找到X 和Y 的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z 既是X 的子序列也是Y 的子序列。

输入

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200 的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

输出

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200 的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

样例输入

abcfbc abfcab
programming contest
abcd mnp

样例输出

4
2
0

分析

状态:maxLen[i][j]表示字符串a左边i个字符与字符串b左边j的字符形成的子串的最大公共子序列长度 (i, j >= 0)。
状态转移方程

if(str1[i-1] == str2[j-1])    maxLen[i][j] = maxLen[i-1][j-1]+1;else maxLen[i][j] = max{maxLen[i][j-1], maxLen[i-1][j]}

实现

此题未给字符串的长度范围,所以我们可以把数据设大些。

#include <iostream>#include <cstring>#include <algorithm>using namespace std;char str1[1000];char str2[1000];int maxLen[1000][1000];int main() {    while (cin >> str1 >> str2) {        int length1 = strlen(str1);        int length2 = strlen(str2);        for (int i = 0; i <= length1; i++)            maxLen[i][0] = 0;        for (int j = 0; j <= length2; j++)            maxLen[0][j] = 0;            for (int i = 1; i <= length1; i++) {                for (int j = 1; j <= length2; j++) {                    if (str1[i - 1] == str2[j - 1])                        maxLen[i][j] = maxLen[i - 1][j - 1] + 1;                    else                        maxLen[i][j] = max(maxLen[i][j - 1], maxLen[i - 1][j]);                }            }        cout << maxLen[length1][length2] << endl;    }    return 0;}

还有不假定长度范围的版本,速度会慢些,但也可以通过测试。

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <vector>using namespace std;string str1, str2;int main(){//  freopen("in.txt", "r", stdin);    while (cin >> str1 >> str2) {        const int str1Length = str1.length();        const int str2Length = str2.length();        int sencondLength = str2Length + 1;        //用一维数组模拟二维数组        int *maxLen = new int[sencondLength * (str1Length + 1)];        //边界条件        for (int i = 0; i <= str1Length; i++) {            maxLen[sencondLength * i + 0] = 0;        }        for (int j = 0; j <= str2Length; j++) {            maxLen[sencondLength * 0 + j] = 0;        }        for (int i = 1; i <= str1Length; i++) {            for (int j = 1; j <= str2Length; j++) {                //状态转移方程                if (str1[i - 1] == str2[j - 1]) {                    maxLen[sencondLength * i + j] = maxLen[sencondLength * (i - 1) + (j - 1)] + 1;                }                else {                    maxLen[sencondLength * i + j] = max(maxLen[sencondLength * i + (j - 1)], maxLen[sencondLength * (i - 1) + j]);                }            }        }        cout << maxLen[sencondLength * str1Length + str2Length] << endl;        delete[] maxLen;    }    return 0;}
0 0
原创粉丝点击