【GDOI2016Day1】第二题 最长公共子串

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

这里写图片描述

Sample Output

这里写图片描述

Data Constraint

这里写图片描述

分析

如果两个操作区间有交集,那么可以把它们合并。(容易证明)
n,m较小,可以设f[i][j] 表示从S和T的第i、j个位置开始最多能匹配多少位。直接计算会超时,因此考虑dp

对于S的一个位i,用l[i],r[i]表示它所在的操作区间的两个边界(如果它不被包含,则视作它被[i..i]包含,即l[i]=r[i]=i)。
对于一个公共子串S[i..i+len],它可能跨过很多个操作区间。设它跨过k个区间,那么第2——k-1个区间都是全部匹配的,最后一个匹配了若干位,第1个匹配了r[i]-i+1个字符。而且确定了第一个区间从T串的哪里开始匹配,就可以推出其它区间的了。
那么我们可以设g[i][j],表示由i (i==l[i]) 开始的区间,T串从j开始,能匹配多少个字符。O(nm)即可预处理出。
然后对于f[i][j],只要用g[i][j]判断是否能匹配到g[i][j],如果可以就从f[r[i]+1][r[i]+1+j-i]转移过来即可。

时间复杂度 O(nm)

dp主要部分

for (int i=0;i<n;i++) if (l[i]==i)
    {
        memset(cnt,0,sizeof(cnt));
        int j;
        for (j=i;l[j]==i;j++) cnt[S[j]]++;
        for (j=0;j<m && cnt[T[j]];j++) cnt[T[j]]--;
        g[i][0]=j;
        for (int k=1;k<m;k++)
        {
            if (j>=k) cnt[T[k-1]]++;else j=k;
            for (;j<m && cnt[T[j]];j++) cnt[T[j]]--;
            g[i][k]=j-k;
        }
    }
    for (int i=n-1;i>=0;i--)
        for (int j=0;j<m;j++)
            if (g[l[i]][j]+i-1<r[i] || g[l[i]][j]+i==m) f[i][j]=g[l[i]][j];else
                f[i][j]=f[r[i]+1][r[i]+1+j-i]+r[i]-i+1;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值