题目点这里直达
题意很明确,就是字典树的裸题。
该数据结构的典型应用是统计,排序和保存大量的字符串(但不仅限于字符串)
资料 1:OI Wiki
资料 2 :http://ddrv.cn/a/44982
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=500001;
struct trie
{
int nex[maxn][26], cnt; //nex[i][j]表示编号为i的节点的第j个孩子的编号;j是按照字符序存储的,i是编号
bool exist[maxn]; // 该结点结尾的字符串是否存在
int val[maxn]; //val[i]记录编号为i的节点信息
void insert(char *s, int l) // 插入字符串
{
int p = 0;
for (int i = 0; i < l; i++)
{
int c = s[i] - 'a';
if (!nex[p][c])
nex[p][c] = ++cnt; // 如果没有,就添加结点
p = nex[p][c];
++val[p]; // 本题的核心,标记每一种前缀出现了几次
}
exist[p] = 1;
}
bool find(char *s, int l) // 查找字符串
{
int p = 0;
for (int i = 0; i < l; i++)
{
int c = s[i] - 'a';
if (!nex[p][c])
return 0;
p = nex[p][c];
}
return exist[p];
}
int query(char *s,int len)
{
int p=0;
for(int i=0 ;i<len;i++)
{
int c=s[i]-'a';
if(!nex[p][c])
return 0;
p=nex[p][c];
}
return val[p];
}
};
trie a;
int main()
{
char str[120];
// scanf("%s",str);
while (cin.getline(str,12), str[0])
{
int len = strlen(str);
a.insert(str, len);
}
// puts("gg");
// scanf("%s",str);
while (scanf("%s", str) != EOF)
{
int len = strlen(str);
// printf("%d\n",a.find(str,len));
printf("%d\n",a.query(str,len));
}
return 0;
}