统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 70313 Accepted Submission(s): 24252
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2
3
1
0
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251
solution:直接使用指针形式的字典树导致内存超限了,后面用数组实现的就过了、看来链表形式的耗内存更多啊
指针形式:(用来学习字典树)
#include <bits/stdc++.h>
using namespace std;
struct TRIE{
TRIE* next[26];
int cnt;
TRIE(){
for (int i = 0; i < 26; ++i)next[i] = NULL;
cnt = 0;
}
}root;
void insert(string word)
{
TRIE *p = &root;
for (int i = 0; i < word.length(); ++i){
if (p->next[word[i] - 'a'] == NULL)p->next[word[i] - 'a'] = new TRIE;
p = p->next[word[i] - 'a'];
++p->cnt;
}
}
int find(string word){
TRIE *p = &root;
for (int i = 0; i < word.length(); ++i){
if (p->next[word[i] - 'a'] == NULL)return 0;
p = p->next[word[i] - 'a'];
}
return p->cnt;
}
int main()
{
string word;
while (getline(cin, word)){
if (word.length() == 0)break;
insert(word);
}
while (getline(cin, word))printf("%d\n", find(word));
return 0;
}
数组形式:
#include <bits/stdc++.h>
using namespace std;
int trie[1000010][26], num[1000010], pos = 1;
void insert(char word[])
{
int c = 0;
for (int i = 0; word[i]; ++i){
int n = word[i] - 'a';
if (trie[c][n] == 0)trie[c][n] = pos++;
c = trie[c][n];
++num[c];
}
}
int find(char word[])
{
int c = 0;
for (int i = 0; word[i]; ++i){
int n = word[i] - 'a';
if (trie[c][n] == 0)return 0;
c = trie[c][n];
}
return num[c];
}
int main()
{
char word[11];
while (gets(word)){
if (word[0] == NULL)break;
insert(word);
}
while (gets(word))printf("%d\n", find(word));
return 0;
}