Common Subsequence Gym - 102307C 公共序列

2019 ICPC Universidad Nacional de Colombia Programming Contest C D J

 

C. Common Subsequence

题意:给出长度为n两个串,求两个串的最长公共子序列len,如果len>=0.99*n,两个串就是亲兄弟否则不是。

解法:朴素的求LCS的时间复杂度是O(nm),这题肯定超时。正解不容易想,要注意到0.99这个特点,我们从这个特点下手也就是说最多只能抛弃0.01*n=1000个字符,

那么我们设dp[i][j]为A串前i+dp[i][j]个字符抛弃掉i个字符,B串前j+dp[i][j]个字符抛弃掉j个字符获得的LCS长度为dp[i][j]。

那么对于此时枚举到的dp[i][j],i+dp[i][j]就是A串已经完成匹配的字符,j+dp[i][j]就是B串完成匹配的字符,换句话说就是AB串接下来开始的位置已经确定了,接下来我们继续从下一个字符开始匹配。

dp[i][j]匹配完之后,A[i+dp[i][j]+1]和B[j+dp[i][j]+1]不相等,那么只能有两种选择抛弃A[i+dp[i][j]+1]或者抛弃B[j+dp[i][j]+1]。所以用dp[i][j]去更新这两个值

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
char A[N],B[N];
int n,m,ans,dp[1010][1010];

int main()
{
    scanf("%s%s",A+1,B+1);
    n=strlen(A+1);
    m=min(1000,n);
    for (int i=0;i<=m;i++)
        for (int j=0;j<=m;j++) {
            while (A[i+dp[i][j]+1]==B[j+dp[i][j]+1] && i+dp[i][j]+1<=n && j+dp[i][j]+1<=n) dp[i][j]++;
            dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
            dp[i][j+1]=max(dp[i][j+1],dp[i][j]);
            ans=max(ans,dp[i][j]);
        }
    if (100*ans>=99*n) puts("Long lost brothers D:"); else puts("Not brothers :(");
    return 0;
}

 

posted @ 2019-09-14 11:57  downrainsun  阅读(290)  评论(0编辑  收藏  举报