POJ 1458 Common Subsequence
题目链接:POJ 1458
Description
Cry对于泡妹子十分不熟练,在见到小姐姐后十分紧张,这时,他想起了czh对他的教诲,于是他决定尽可能找到自己与小姐姐的共同点。Cry靠他强大的人格魅力获取了小姐姐的基因片段,同时他也提供了自己的基因片段,现在我们假定,他们的公共点个数为两个片段的最长公共子序列中元素个数,cry有点方因为他完全不会做,他的幸福生活只能靠在座的各位了!
Input
多组输入,每行有两个字符串,根据本czh的经验,如果对小姐姐问来问去是很失礼的一件事,因此每个基因片段长度最好不超过1000吧
Output
每行一个答案,表示每组数据中他们的公共点个数
Sample Input
abcfbc abfcab
programming contest
abcd mnp
Sample Output
4
2
0
题意
求两个字符串的最长公共子序列。
首先先了解一下子序列
子序列
在数学中,某个序列的子序列是从最初序列通过去除某些元素但不破坏余下元素的相对位置(在前或在后)而形成的新序列。
题解:
所谓的最长子序列,就是两个字符串有多少相对位置相同的字母,dp[i][j]表示第一个字符串的前i个字母和第二个字符串的前j个字母的最长公共子序列,状态转移式为
if (a[i - 1] == b[j - 1])
DP[i%2][j] = DP[(i - 1)%2][j - 1] + 1;
else DP[i%2][j] = max(DP[i%2][j - 1], DP[(i - 1) % 2][j]);
这里用到了滚动数组,用i%2实现对数组的重复利用。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
const int N = 1e3+5;
char a[N];
char b[N];
int DP[2][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
while (cin >> a >> b) {
memset(DP, 0, sizeof DP);
int lenth1 = strlen(a);
int lenth2 = strlen(b);
for (int i(1); i <= lenth1; i++)
for (int j(1); j <= lenth2; j++)
if (a[i - 1] == b[j - 1])
DP[i%2][j] = DP[(i - 1)%2][j - 1] + 1;
else DP[i%2][j] = max(DP[i%2][j - 1], DP[(i - 1) % 2][j]);
cout << DP[lenth1%2][lenth2] << endl;
}
return 0;
}