原题:http://acm.hdu.edu.cn/showproblem.php?pid=1251
题意:
给出一些单词;
下面给出一些字符串,计算以该字符串为前缀的单词个数;
思路:
字典树模板题,只要在插入单词的时候每个字母所路过的节点的val都+1;
#include<stdio.h>
#include<string.h>
#define MAX 26
const int maxnode=4000*100+100;//预计字典树最大节点数目
const int sigma_size=26;//每个节点的最多儿子数
struct Trie
{
int ch[maxnode][sigma_size];//ch[i][j]==k表示第i个节点的第j个儿子是节点k
int val[maxnode];//val[i] == x表示第i个节点的权值为x
int sz;//字典树一共有sz个节点,从0到sz-1标号
//初始化
void init()
{
sz = 1;
memset(val, 0, sizeof val);
memset(ch[0], 0, sizeof ch[0]); //ch值为0表示没有儿子
}
//返回字符编号
int idx(char c)
{
return c-'a';
}
//在字典树中插入单词s,但是如果已经存在s单词会重复插入且覆盖权值
//所以执行insert前需要判断一下是否已经存在s单词了
void insert(char s[])
{
int u = 0, n = strlen(s);
for(int i = 0;i<n;i++)
{
int id = idx(s[i]);
if(ch[u][id] == 0) //无该儿子
{
ch[u][id] = sz;
memset(ch[sz], 0, sizeof ch[sz]);
sz++;
}
u=ch[u][id];
val[u]++;
}
}
//在字典树中查找单词s
int search(char s[])
{
int n = strlen(s), u = 0;
for(int i = 0;i<n;i++)
{
int id = idx(s[i]);
if(ch[u][id] == 0)
return 0;
u = ch[u][id];
}
return val[u];
}
}trie;
int main()
{
char str[15];
trie.init();
while(gets(str))
{
if(str[0] == NULL)
break;
trie.insert(str);
}
while(gets(str))
{
if(str[0] == NULL)
break;
int ans = trie.search(str);
printf("%d\n", ans);
}
return 0;
}