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
思路:
主要是在每一段区间内,在期间长度大于单词长度的情况下,对单词进行判断,这个区间内还需要删掉多少个单词,并做记录,状态转移方程为:dp[i] = min(d[j]+区间(i,j)内最少删除单词的个数).
一种比较直白的思路,不过会超时.
#include<stdio.h>
#include<string.h>
char word[500][30];
char a[400];
int sum[500];
int pipei(int l,int r,char *p)
{
int len = strlen(p);
int j = 0;
for(int i = l; i <= r && r-i+1 >= j; i++)
{
if(a[i] == p[j])
j++;
}
// printf("%d\n",r-l-j);
return r-l-j+1;
}
int main(){
for(int i = 0; i < 400; i++){
sum[i] = 500;
}
sum[0] = 1;
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",a);
for(int i = 0; i < n; i++)
scanf("%s",word[i]);
for(int i = 0; i < m; i++){
sum[i] = i+1;
int min1 = 500;
for(int j = 0; j < i; j++){
for(int k =0; k < n; k++){
if(j-i+1 < strlen(word[i]))
continue;
int x = sum[j] + pipei(j,i,word[k]);
if(x < min1)
min1 = x;
}
if(sum[i] > min1)
sum[i] = min1;
}
}
printf("%d\n",sum[n-1]);
return 0;
}
这种方法的话思路看起来比较直白,不过在匹配上要花时间确定左区间,所以时间上话费了一些时间(并不能AC),在优化后,不需要先确定左区间,从右区间遍历, 这个时间复杂度上相对来说优化了很多,而且能AC
-
#include <iostream>
-
#include <stdio.h>
-
#include <algorithm>
-
#include <stdlib.h>
-
#include <math.h>
-
#include <string.h>
-
#include <vector>
-
#include <queue>
-
#include <stack>
-
#include <map>
-
#include <set>
-
using namespace std;
-
int w,l;
-
int dp[2333];
-
char key[2333];
-
char dic[2333][233];
-
int min(int a,int b)
-
{
-
if(a<b) return a;
-
else return b;
-
}
-
int main()
-
{
-
cin>>w>>l;
-
scanf("%s",key);
-
for(int i=1;i<=w;i++)
-
{
-
scanf("%s",dic[i]);
-
}
-
dp[0]=1;
-
for(int i=1;i<l;i++)
-
{
-
dp[i]=dp[i-1]+1;
-
int len;int k;
-
for(int j=1;j<=w;j++)
-
{
-
len=strlen(dic[j])-1;
-
k=i;
-
if(len>i) continue;
-
while(len>=0&&k>=0&&k>=len)
-
{
-
if(key[k]==dic[j][len]) len--;
-
k--;
-
}
-
if(len<0) dp[i]=min(dp[i],dp[k]+i-k-strlen(dic[j]));
-
}
-
}
-
cout<<dp[l-1];
-
return 0;
-
}