Codeforces A ACM (ACronym Maker) (dp)

http://codeforces.com/gym/100650

概要:给出一个缩写,和一些单词,从单词中按顺序选一些字母作为缩写,问方案数。

限制:某些单词要忽略,每个单词至少要选一个字母。

dp[i][j]表示到第i个单词的时候已经选了j个字母的方案数。

很明显,当前字符ch是第j个字符的时候,第j-1个字母只能在上一个单词或者这个单词中ch之前出现,所以有dp[i][j] += dp[i][j-1] + dp[i-1][j-1]。

边界条件为dp[i][0] = 1。由于i只由i-1和自身决定因此可用滚动数组优化。

#include<bits/stdc++.h>
using namespace std;

int n;
const int maxn = 166;
char str[maxn];
char tar[maxn];
char word[maxn];

int sscan_line(char *s,char *&s0)
{
    if(!*s0) return 0;
    int i = 0, j = 0;
    while(s0[i] == ' ') i++;
    for(j = 0;s0[i] && s0[i] != ' '; i++){
        s[j++] = s0[i];
    }
    s[j] = ''; s0+=i;
    return j;
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)&&n){
        set<string> ig;
        while(n--){
            scanf("%s",str);
            ig.insert(str);
        }
        scanf("
");
        while(gets(str) && strcmp(str,"LAST CASE") != 0){
            //stringstream sin.(str)
            char *p = str;
            int tlen = sscan_line(tar,p);
            int dp[maxn]={} ; dp[0] = 1;
            for(int i = 0; tar[i]; i++){
                tar[i] += 'a'-'A';
            }
            while(sscan_line(word,p)){
                if(ig.count(word) != 0) continue;
                int ndp[maxn]={};
                for(int i = 0; word[i]; i++)
                    for(int j = tlen-1; ~j; j--)
                        if(word[i] == tar[j])
                            ndp[j+1] += dp[j]+ndp[j];
                copy(ndp,ndp+maxn,dp);
            }
            for(int i = 0; i < tlen; i++){
                tar[i] -= 'a'-'A';
            }
            int ans = dp[tlen];
            if(ans) printf("%s can be formed in %d ways
",tar,ans);
            else printf("%s is not a valid abbreviation
",tar);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4740823.html