ACM题“Harry Potter and His Magic Scroll”的一种解法
1. 题目
该题目原文见HDU ACM 2664:
http://acm.hdu.edu.cn/showproblem.php?pid=2664
或WHU ACM 1360:
http://acm.whu.edu.cn/oak/problem/problem.jsp?problem_id=1360
2. 需求解析
根据题意可解析出如下需求:
a) 输入的第1行是用例数。
b) 输入的每个用例中有一个词典。词典最多包含100000个单词,单词之间只用一个空格符隔开,一个单词可能跨2行,每个单词的长度不超过20。
c) 按行输入词典,每行最多包含2000个字符,最后一行只有一个字符“#”,表示词典结束。
d) 词典结束后的下一行输入是一个整数T,表示文卷数。
e) 文卷数的下一行输入是一个整数m,表示文卷中要包含的魔力单词数。
f) 随后输入m行魔力单词,每个单词的长度不超过20。
g) 在词典中寻找包含一个文卷的所有魔力单词的一段连续的单词(以下简称为passage)。
h) 魔力单词与词典中的单词大小写相同。
i) 魔力单词在这段单词中出现的位置可以是任意的。
j) 由于要求是连续的,这段单词可能包含非魔力单词。
k) 这段连续的单词应是在词典中最短的,并且是最先出现的。
l) 输出这段连续的单词的首字符和尾字符在词典中的位置,词典中第一个字符的位置为0。
3. 数据结构设计
#define MAX_LINE 2002
#define MAX_WORD_NUMBER 100001
#define MAX_WORD_LENGTH 21
#define MAX_PASSAGE_LENGTH /
(MAX_WORD_NUMBER*MAX_WORD_LENGTH)
typedef struct
{
char word[MAX_WORD_LENGTH];
int start_position;
int end_position;
int magic_id; /*词典单词所对应的魔力单词编号,
从0 开始,-1表示不是魔力单词*/
} dict_word_type; /*词典单词属性*/
char line[MAX_LINE]; /*输入的一行辞典内容*/
dict_word_type dictionary[MAX_WORD_NUMBER]; /*词典*/
int dictionary_word_number;/*词典单词总数*/
unsigned case_number; /*用例数*/
unsigned scroll_number; /*文卷数*/
int magic_word_number; /*魔力单词数*/
int magic_word_length_sum; /*魔力单词长度总和*/
int search_start; /*第一个魔力单词在辞典中的编号*/
int word_count_for_dictionary[MAX_WORD_NUMBER];/*辞典中每个魔力单词的出现次数*/
int word_count_for_passage[MAX_WORD_NUMBER]; /*辞典中一段单词中每个魔力单词的出现次数*/
4. 算法设计
读入case_number;
while (case_number--)
{
按行读入词典内容;
存入dictionary并计算每个单词的属性;
读入scroll_number;
while (scroll_number--)
{
读入魔力单词并计算词典中每个单词的魔力单词编号和word_count_for_dictionary;
在词典寻找最先出现的passage(用指针p和q分别其首单词和尾单词);
minimun_length = MAX_PASSAGE_LENGTH;
for (;;)
{
计算p到q之间的长度k;
if (minimun_length > k)
{
minimun_length = k;
保存p和q中的位置到best_first_position和best_last_position;
if (k == magic_word_length_sum) break;
}
取p的magic_id;
移动p和/或q使其指向下一段passage;
if (没有新的passage) break;
}
输出最短passage的首尾位置;
}
}
5. 测试用例
输入:
1
Potter to Harry want to make scrolls some Harry going Harry go
ing to Potter improve some scrolls
to his magic power.
#
2
1
to
3
Harry
Potter
going
输出:
7 8
54 74
6. 结论
本题的关键是正确解析题意和设计高效的搜索算法。