题意:给你两个只有ATCG组成的等长字符串,问他们的LCS(最长公共子序列)是否大于|s|*0.99。
题解:
刚开始想到的是字符串只有ATCG,仅仅四个,会不会有什么性质。然后赛后发现做出这题不用这个性质。=. =||
我们可以发现,要想LCS>99%,我们最多在每个串上可以舍弃1e5*0.01也就是1000个字符。那我们设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为第一个串舍弃i个字符,第二个串舍弃j个字符所能得到的最长的相同前缀。那么我们要计算
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]的时候,
d
p
[
i
]
[
j
]
+
i
dp[i][j]+i
dp[i][j]+i就是第一个串目前所在位置,
d
p
[
i
]
[
j
]
+
j
dp[i][j]+j
dp[i][j]+j就是第二个串目前所在的位置。这时候我们先暴力往后匹配,看最多能跑多远,然后更新
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j],此时
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]才为最终结果。然后在用
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]更新
d
p
[
i
+
1
]
[
j
]
dp[i+1][j]
dp[i+1][j]与
d
p
[
i
]
[
j
+
1
]
dp[i][j+1]
dp[i][j+1]。这个过程中,最大的
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]就是答案,用这个来比较就行了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5+5;
char s[maxn],t[maxn];
int dp[1005][1005];
int main(){
scanf("%s%s",s,t);
int n = strlen(s);
int d = min(n,1000);//这里最多是1000,改成d = n*0.01不会影响结果
int ret=0;
for(int i=0;i<=d;i++){
for(int j=0;j<=d;j++){
int len = dp[i][j];
while(i+len<n&&j+len<n&&s[i+len]==t[j+len]){
dp[i][j]++,len++;
}
dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
dp[i][j+1]=max(dp[i][j+1],dp[i][j]);
ret = max(dp[i][j],ret);
}
}
if(ret*100>=n*99)puts("Long lost brothers D:");
else puts("Not brothers :(");
return 0;
}