POJ 3267 The Cow Lexicon( DP~去掉最少字符)

来源:互联网 发布:linux配置yum软件仓库 编辑:程序博客网 时间:2024/03/28 16:56
The Cow Lexicon
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 8319 Accepted: 3931

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 10browndcodwcowmilkwhiteblackbrownfarmer

Sample Output

2
两个整数m,n,接下来一行是n个小写字母组成的母串(用a表示),然后是m个串(用si表示,bi表示si的长度),闻母串最少去掉多少个字母后,可以由下面若干个串连接起来组成。。
对于示例, 在"browndcodw"中去掉两个'd'后变为"browncow" ,可由s5 "brown"和s1 "cow"连接而成
所以结果为2
好好的一个DP,愣是让我写成了贪心,然后这个很水的示例还让我过了,WA了数遍后,看了[Discuss]中有人发的测试数据后,我才发现写的贪心取得最优仅仅是限于当前,在遍历母串的时候,贪心取得的最优就不是最优了。。。
dp[i]表示母串1~i中,去掉字母的最小数目;
对于母串,如果存在一段 aj ~ ai(j<i && i-j+1 >= bk) 中存在一个sk(长度为bk),则这一段去掉字母数为 i-j+1-bk
所以我们可以得到 d[i] = min( dp[i] , dp[j-1] + i-j+1-bk )。
#include <iostream>#include <stdlib.h>#include <cstdio>#include <cstring>using namespace std;const int N = 610;int main(){    int n,m;    while(~scanf("%d%d%*c",&m,&n))    {        char s[N][30],a[N];        int b[N];        for(int i=1;i<=n;i++)            scanf("%c",&a[i]);           //母串           for(int i=0; i<m; i++)        {            scanf("%s",s[i]);             //匹配串            b[i]=strlen(s[i]);             //记录匹配串长度        }        int dp[N];        dp[0]=0;        for(int i=1; i<=n; i++)        {            dp[i]=dp[i-1]+1;               //如果没有匹配,母串每多一个字母,为前一状态+1            for(int k=0; k<m; k++)            {                if(i<b[k]) continue;       //母串的一段长度小于匹配串的长度,不会存在匹配                int an=b[k]-1;             //倒着进行匹配,匹配成功后的 j 为母串开始匹配的位置,i为结束的位置                for(int j=i; j>=1; j--)                {                    if(a[j] == s[k][an])                        an--;                    if(an<0)                  //匹配成功的条件                        dp[i]=min(dp[i],dp[j-1]+i-j-b[k]+1);                }            }        }        printf("%d\n",dp[n]);    }    return 0;}// 一组数据,结果应为4/*9 20carmrcmddrcaddamroomcarcdrcadarmoooomomomrcamroom*/


0 0