zoukankan      html  css  js  c++  java
  • 【BZOJ】1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典(dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1633

    一开始也想到了状态f[i]表示i以后的字符串最少删的数

    然后想到的转移是

    f[i]=min{f[i+1]+1, f[i+len[a]]}

    但是没想到。。。。后边其实不是完全匹配到整个单词,,而是可以删的。。

    那么就转换一下,。

    f[i]=min{f[i+1]+1, f[i+len[a]+t]+t} t为i开始后找到单词a要删的字母个数。。

    这里可以优化,当a[0]==b[i]时,才进行转移。

    这几乎是显然的,因为我们是从后向前推,因此,在j<i时,如果a在i时已经转移,那么j的最优答案显然不会再找这个a,因为不会重复(或者说啥。。。自己想想一下。。)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int L=305, N=606;
    int f[L], n, m, len[N];
    char a[N][30], b[L];
    int check(int x, int y) {
    	if(len[x]+y-1>=m) return -1;
    	int tot=0, i=0, ln=len[x];
    	while(y<m) {
    		if(a[x][i]==b[y]) ++i;
    		else ++tot;
    		if(i==ln) return tot;
    		++y;
    	}
    	return -1;
    }
    int main() {
    	read(n); read(m);
    	scanf("%s", b);
    	for1(i, 1, n) {
    		scanf("%s", a[i]);
    		len[i]=strlen(a[i]);
    	}
    	for3(i, m-1, 0) {
    		f[i]=f[i+1]+1;
    		for1(j, 1, n) if(a[j][0]==b[i]) {
    			int t=check(j, i);
    			if(t==-1) continue;
    			f[i]=min(f[i], f[i+len[j]+t]+t);
    		}
    	}
    	printf("%d", f[0]);
    	return 0;
    }
    

    Description

    没 有几个人知道,奶牛有她们自己的字典,里面的有W (1 ≤ W ≤ 600)个词,每个词的长度不超过25,且由小写字母组成.她们在交流时,由于各种原因,用词总是不那么准确.比如,贝茜听到有人对她 说"browndcodw",确切的意思是"browncow",多出了两个"d",这两个"d"大概是身边的噪音. 奶牛们发觉辨认那些奇怪的信息很费劲,所以她们就想让你帮忙辨认一条收到的消息,即一个只包含小写字母且长度为L (2 ≤ L ≤ 300)的字符串.有些时候,这个字符串里会有多余的字母,你的任务就是找出最少去掉几个字母就可以使这个字符串变成准确的"牛语"(即奶牛字典中某些词 的一个排列).

    Input

    第1行:两个用空格隔开的整数,W和L.

    第2行:一个长度为L的字符串,表示收到的信息. 第3行至第W+2行:奶牛的字典,每行一个词.

    Output

    唯一一行:一个整数,表示最少去掉几个字母就可以使之变成准确的"牛语".

    Sample Input

    6 10
    browndcodw
    cow
    milk
    white
    black
    brown
    farmer

    Sample Output

    2

    HINT

    Source

  • 相关阅读:
    数组的一些经典案例(循环)(max=score[0])(冒泡)(flag标志)(杨辉三角)
    冒泡排序
    C语言之数组
    循环结构的一些案例:倒等腰三角形、菱形、暴力破解
    break和contine关键字
    循环嵌套(打印*** ***)
    循环的经典案例(李白买酒)
    C语言循环结构-while/do...while/for--逢3过,阶乘,九九乘法表
    WordPress部署踩坑记
    Symbol
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3960246.html
Copyright © 2011-2022 走看看