题目描述
L 星球上的生物由蛋蓝质组成,每一种蛋蓝质由一类称为蓝肽的物资首尾连接成一条长链后折叠而成。
生物学家小乔正在研究 L 星球上的蛋蓝质。她拿到两个蛋蓝质的蓝肽序列,想通过这两条蓝肽序列的共同特点来分析两种蛋蓝质的相似性。
具体的,一个蓝肽可以使用 111 至 555 个英文字母表示,其中第一个字母大写,后面的字母小写。一个蛋蓝质的蓝肽序列可以用蓝肽的表示顺序拼接而成。
在一条蓝肽序列中,如果选取其中的一些位置,把这些位置的蓝肽取出,并按照它们在原序列中的位置摆放,则称为这条蓝肽的一个子序列。蓝肽的子序列不一定在原序列中是连续的,中间可能间隔着一些未被取出的蓝肽。
如果第一条蓝肽序列可以取出一个子序列与第二条蓝肽序列中取出的某个子序列相等,则称为一个公共蓝肽子序列。
给定两条蓝肽序列,找出他们最长的那个公共蓝肽子序列的长度。
输入描述
输入两行,每行包含一个字符串,表示一个蓝肽序列。字符串中间没有空格等分隔字符。
其中有 ,两个字符串的长度均不超过 100010001000。
输出描述
输出一个整数,表示最长的那个公共蓝肽子序列的长度。
题解:这道题其实就是个最长公共子序列的问题,只不过原来可能是单个字符,这题是一个单词,所以这题需要先预处理出来每一个单词,然后再用最长公共子序列的策略做。
最长公共子序列解法:
状态表示:f[i,j] 表示a串的前i个单词与b串的前j个单词有多少个单词相同的方案数
状态转移方程:假如i和j这个位置上的单词不相同,则可能当前i可能和前j-1个单词匹配或者j和前i-1个单词匹配的二者最大值:若相同的话,就是前i-1和j-1的方案数+1。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int f[N][N];
string s1,s2;
string a[N],b[N];
int n,m;
int main()
{
cin>>s1>>s2;
for(int i = 0;s1[i];){
n++;
if(s1[i] >= 'A' && s1[i] <= 'Z'){
a[n] += s1[i++];
while(s1[i]>='a' && s1[i]<='z') a[n] += s1[i++];
}
}
for(int i = 0;s2[i];){
m++;
if(s2[i]>='A' && s2[i]<='Z'){
b[m] += s2[i++];
while(s2[i]>='a' && s2[i]<='z') b[m] += s2[i++];
}
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
if(a[i] == b[j]) f[i][j] = f[i-1][j-1]+1;
else f[i][j] = max(f[i-1][j],f[i][j-1]);
}
}
cout<<f[n][m]<<endl;
return 0;
}