算法分析和复杂性理论 / 22年算法课上机题目合集AA:Common Subsequence【POJ-1458】

题目Common Subsequence

描述

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, ..., ik > of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

输入

The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

输出

For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

样例输入

abcfbc abfcab

programming contest

abcd mnp

样例输出

4

2

0

思路分析

    题目:最长公共子序列,可以不相邻地找出两个字符串中最长的重复部分长度

    输入:多行数据,每行是要求最长公共子序列的两个字符串

    解决方案:动态规划,假设字符串str1 str2长度分别为M和N,那就建立一个dp[M+1][N+1]的二维数组,其中dp[i][j]代表str1的前i个字符(str[0]至str[i-1])和str2的前j个字符(str[0]至str[j-1])的最长公共子序列长度。边界条件dp[0][:]和dp[:][0]为0,因为有一个字符串没有长度,比较的时候自然没有重复部分。状态转移方程有两种情况,如果求dp[i][j]时,str1的第i个和str2和第j个元素刚好相同,则dp[i][j]=dp[i-1][j-1]+1,如果不相同,则等于dp[i-1][j]和dp[i][j-1]中的最大值。

    注意的细节:字符串的第i个字符,实际索引是str[i-1],因为string类型从0开始;判断条件中dp[i-1][j-1]+1一定大于等于max(dp[i-1][j],dp[i][j-1]),因为dp[i-1][j]只比dp[i-1][j-1]多了一个字符,因此最多比它大1,因此dp[i-1][j-1]加1后一定大于等于dp[i-1][j],dp[i][j-1]同理。这一点从dp数组的第二行开始推也能很容易想通。

过程中的错误

    调试代码时初始化数组dp[1005][1005]时发生栈溢出,因为局部变量无法开这么大,因此采用了静态局部变量来解决,将它归到Data Segment中。

    相关知识[静态局部变量]:在局部变量前加上“static”关键字,就成了静态局部变量。静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。静态局部变量的初始化与全局变量类似.如果不为其显式初始化,则C++自动为其初始化为0。静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它的函数中可见。静态局部变量与局部变量在存储位置上不同,使得其存在的时限也不同,导致对这两者操作 的运行结果也不同。

AC代码

 

#include <iostream>
#include <string>
using namespace std;

int main() {
    static int dp[1005][1005] = { 0 };
    string a, b;
    while (cin >> a >> b) {
        int m = a.size(), n = b.size();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (a[i] == b[j]) {
                    dp[i + 1][j + 1] = dp[i][j] + 1;
                }
                else {
                    dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);
                }
            }
        }
        cout << dp[m][n] << endl;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值