ECNU CCCC选拔赛 E题 Teacher Panda and plagiarism dp

英语作⽂的 Online Judge 真不是什么靠谱的系统,它有的时候连⽂章是否是抄袭也分不出来。So sad!熊猫⽼师,ECNU 英语教师,对此事表⽰⾮常⽣⽓。在周⼀的英语课上,他⼤发雷霆,谈论抄袭的弊端。

他甚⾄对抄袭⾏为进⾏了分类:

• 相似度⼤于 20%,认定为抄袭 (COPY);

• 相似度⼤于 60%,认定为剽窃 (PLAGIARISM);

• 相似度为 100%,认定为「谋杀」(MURDER)。

为了避免同学们互相「谋杀」,熊猫⽼师决定⾃⼰对同学们的作⽂进⾏抄袭认定⼯作。ECNU 的同学们,为了抵抗熊猫⽼师的剽窃禁⽌令,不惜⼀切代价,甚⾄不惜把作⽂去掉标点去掉空格全部连在⼀块⼉写。他们觉得,这样就能阻⽌熊猫⽼师认出他们的抄袭作⽂。事实证明,这样的抵抗确实是有效的。熊猫⽼师现在甚⾄需要⼀个程序才能判断⼀篇作⽂是否存在抄另外⼀篇的嫌疑。当然程序是很傻的,它需要⾮常傻的逻辑语⾔才能运⾏。

于是熊猫⽼师摈弃了他上英语课时⼀贯的风流潇洒,说出了下⾯⼀段话:

有长度均为 n 的字符串 A 和字符串 B。从 A 字符串中取出若⼲个互不重叠的长度⾄少为 k 的⼦串,将它们按出现顺序组成序列 S(不是串成字符串)。从 B 中也取出若⼲个,组成序列 T。如果序列 S 恰好与序列 T 相同,那么称这个序列是 A和 B 的公共单词序列。求 A 和 B 的所有公共单词序列中最长的那⼀个的长度。

Input:

输⼊不超过 40 组测试数据。对于每组数据:

第⼀⾏是两个整数 n, k (1 ≤ k ≤ n ≤ 2 × 103),表⽰字符串的长度。

第⼆⾏和第三⾏分别有⼀个长度为 n 的字符串。字符串中只会出现⼩写英⽂字母。

Output:

输出对于每组数据,输出最长公共单词序列的长度。

________________________________________________________________________________________________________________________________________________

定义状态dp(i,j)表示第一个字符串前i个字符和第二个字符串前j个字符串最长单词序列的长度。

if (i和j有长度大于等于k的后缀)

dp(i, j) = dp(i - k, j - k) + 1;

else

dp(i, j) = max(dp(i - 1, j), dp(i, j - 1));

代码如下:

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <iostream>
#include <algorithm>
#include <cmath>
#define MAX_N 2005

using namespace std;

typedef long long int ll;
char txt1[MAX_N], txt2[MAX_N];
int dp[MAX_N][MAX_N], suffix[MAX_N][MAX_N];

int main()
{
    //freopen("1.txt", "r", stdin);

    int n, k;

    while (~scanf("%d%d", &n, &k))
    {
        scanf("%s%s", txt1, txt2);

        memset(suffix, 0, sizeof(suffix));
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
        {
            if (txt1[i - 1] == txt2[j - 1])
                suffix[i][j] = suffix[i - 1][j - 1] + 1;
            else
                suffix[i][j] = 0;
        }

        memset(dp, 0, sizeof(dp));
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
        {
            if (suffix[i][j] >= k)
                dp[i][j] = dp[i - k][j - k] + 1;
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }

        printf("%d\n", dp[n][n]);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值