题目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;
}
}