题目
Manuel thinks that Diego is his long lost brother. But Diego thinks Manuel is wrong, and to prove it, he got DNA samples from himself and Manuel. Now Diego has given you the DNA samples and it is your task to say whether they are brothers or not.
The DNA samples of Diego and Manuel are strings A and B, both have length nn (1≤n≤1051≤n≤105) and consist of only the characters ‘A’, ‘T’, ‘G’ and ‘C’. If there is a common subsequence of A and B that has length greater than or equal to 0.99×n0.99×n, then Diego and Manuel are brothers, in other case, they are not.
Input
The input consists of two lines with strings A and B, respectively.
Output
You should output a single line with “Long lost brothers D:” (without quotes) if Diego and Manuel are brothers, and "Not brothers : ( " (without quotes) if they are not.
题解
最长公共子序列的长度要达到原字符串长度的0.99自认为是“失散多年的兄弟”,否则不是。
如果正向思考,DP求最长公共子序列是O(n^2) TLE(另外要用滚动数组,否则会MLE)
那么,正难则反,因为要达到0.99所以至多删除1000个字母,那么dp删除的字符来得到剩余字符串的长度就可以了
好难的思路,看了题解才会。
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
char a[maxn],b[maxn];
int i,j,dp[1007][1007];//删除的个数
int r;
int ans;
double p;
int main()
{
scanf("%s%s",a,b);
int len=strlen(a);
r=len/100+1;
for(int i=0;i<=r;i++)
for(int j=0;j<=r;j++){
while(i+dp[i][j]<len&&j+dp[i][j]<len&&a[i+dp[i][j]]==b[j+dp[i][j]]) dp[i][j]++;//如果a[i+dp[i][j]]==b[j+dp[i][j]]那么当前dp值增加
dp[i+1][j]=max(dp[i][j],dp[i+1][j]);
dp[i][j+1]=max(dp[i][j],dp[i][j+1]);//填表过程
ans=max(dp[i][j],ans);
}
p=1.0*ans/len;
if(p>=0.99)
cout<<"Long lost brothers D:";
else
cout<<"Not brothers :(";
return 0;
}