POJ 3267 The Cow Lexicon

126 篇文章 2 订阅

这道题目的大体意思是:给你一个字符串,然后再给你若干个字符串,让你把给定的字符串进行删减得到的字符串,可以有下面若干个字符串组成。如:

6 10
browndcodw
cow
milk
white
black
brown
farmer
browndcodw 去掉两个d字母之后就可以由cow和brown两个单词组成。所以最少要删除2个字母。
我一开始是这么想的:判断每一个子符串是不是大字符串的子串,然后根据长度进行dp求可以组成的最大的长度。但这是不科学的啊,(又是不对的,这两天老是不对啊、、)因为如果两个单词共用了一个字母那就不好算了啊、、水了一把试了一下结果wa了。。。
解题思路:以每个字母为一个状态,然后从当前位置i到0判断是否能找到一个子串,如果能找到在dp[i] = min{dp[i],dp[t]+i-t-k}求的最少删除字母的个数。
 
The Cow Lexicon
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 7337 Accepted: 3430

Description

Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no more 25 of the characters 'a'..'z'. Their cowmunication system, based on mooing, is not very accurate; sometimes they hear words that do not make any sense. For instance, Bessie once received a message that said "browndcodw". As it turns out, the intended message was "browncow" and the two letter "d"s were noise from other parts of the barnyard.

The cows want you to help them decipher a received message (also containing only characters in the range 'a'..'z') of length L (2 ≤ L ≤ 300) characters that is a bit garbled. In particular, they know that the message has some extra letters, and they want you to determine the smallest number of letters that must be removed to make the message a sequence of words from the dictionary.

Input

Line 1: Two space-separated integers, respectively:  W and  L 
Line 2:  L characters (followed by a newline, of course): the received message 
Lines 3.. W+2: The cows' dictionary, one word per line

Output

Line 1: a single integer that is the smallest number of characters that need to be removed to make the message a sequence of dictionary words.

Sample Input

6 10
browndcodw
cow
milk
white
black
brown
farmer

Sample Output

2
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <stdlib.h>
#include <cmath>

using namespace std;

char str[1010][101], s[1010];
int dp[10100];
int main()
{
    int i, j, n, m, t, k;
    scanf("%d %d",&n, &m);
    scanf("%s",s);
    for(i = 0; i < n; i++)
        scanf("%s",str[i]);
    dp[0] = 1;
    for(i = 1; i < m; i++)
    {
        dp[i] = dp[i-1]+1;
        for(j = 0; j < n; j++)
        {
            int kk;
            kk = strlen(str[j]);
            k = kk-1;
            if(k > m)
                continue;
            t = i;
            while(t >= 0 && k >= 0 && t >= k)
            {
                if(str[j][k] == s[t])
                    k--;
                t--;
            }
            if(k < 0)
                dp[i] = min(dp[i], dp[t]+i-t-kk);//i-t是删掉前t个数之后还剩多少个单词,-kk代表去掉重复的最终剩多少个;
        }
    }
    printf("%d\n",dp[m-1]);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值