ZOJ: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1387
POJ: http://poj.org/problem?id=1432
题目大意:
给出一个字母的译码表,给出一个有n个单词的字典,给出一串编码。问再给出字典中有多少种不同的解码方式。
题目分析:
首先编码只有-和.,可以很方便地建立一棵Trie树,还是最熟悉的二叉方式。
typedef struct trie
{
int count; //单词数
struct trie *dot, *dash;
}trie;
之后将每一个读入的单词插到Trie树上。
用动态规划处理 Morse sequence, 下面记为str。
记f[i]为第i个字符到strlen(str)-1的不同解码数,f[i]=sum(f[i+j]*count[k], 表示从i开始的j位可以解码为一个单词,且相同编码的单词有count[k]个),具体的count和单词的匹配用之前建立的Trie树完成。
源代码:
Trie树的写法根据看到的一个感觉不错的版本修改过。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define maxn 10010
#define maxlen 20010
const char* morse[26] = {
".-", "-...", "-.-.", "-..",
".", "..-.", "--.", "....",
"..", ".---", "-.-", ".-..",
"--", "-.", "---", ".--.",
"--.-", ".-.", "...", "-",
"..-", "...-", ".--", "-..-",
"-.--", "--.."
};
typedef struct trie
{
int count; //单词数
struct trie *dot, *dash;
}trie;
trie *trie_new()
{
trie *t = (trie *)malloc(sizeof(trie));
t->dot = t->dash = NULL;
t->count = 0;
return t;
}
void trie_add(trie *root, const char code[])
{
int p=0, len=strlen(code);
trie *node=root;
while (p<len)
{
if (code[p]=='.')
{
if (!node->dot)
node->dot = trie_new();
node = node->dot;
}
else
{
if (!node->dash)
node->dash = trie_new();
node = node->dash;
}
p++;
}
node->count++;
}
void trie_free(trie *p)
{
if (p)
{
trie_free(p->dot);
trie_free(p->dash);
free(p);
}
}
void getmorse(const char word[], char code[])
{
int j=0;
for (int i=0; i<strlen(word); i++)
{
int mlen=strlen(morse[word[i]-'A']);
for (int k=0; k<mlen; k++, j++)
code[j]=morse[word[i]-'A'][k];
}
code[j]='\0';
}
void init(char str[], trie *root)
{
int n;
char word[maxlen], code[maxlen];
scanf("%s", str);
scanf("%d", &n);
for (int i=0; i<n; i++)
{
scanf("%s", word);
getmorse(word, code);
trie_add(root, code);
}
}
int dp(const char str[], trie *root)
{
int f[maxn];
int slen=strlen(str);
f[slen]=1;
for (int i=slen-1; i>=0; i--)
{
f[i]=0;
trie *p=root;
for (int j=i; j<slen; j++)
{
if (str[j]=='.')
{
if (p->dot==NULL) break;
p=p->dot;
}
else
{
if (p->dash==NULL) break;
p=p->dash;
}
if (p->count!=0) f[i] += (p->count)*f[j+1];
}
}
return f[0];
}
int main()
{
char str[maxlen];
int cs, ans;
trie *root;
scanf("%d", &cs);
while (cs--)
{
trie_free(root);
root = trie_new();
init(str, root);
ans = dp(str, root);
printf("%d\n", ans);
}
return 0;
}
题目分析:
题目分析:
题目分析:
题目分析: