统计难题
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131070/65535 K (Java/Others)Total Submission(s): 50110 Accepted Submission(s): 17691
Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
注意:本题只有一组测试数据,处理到文件结束.
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
Sample Input
banana
band
bee
absolute
acm
ba
b
band
abc
Sample Output
2
3
1
0
指针字典树:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define MAX 26
struct Tree{
Tree *next[MAX];
int v;
};
Tree *root;
void careTree(char *str)
{//构建
int len=strlen(str);
Tree *p=root,*q;
for(int i=0;i<len;i++)
{
int id=str[i]-'a';
if(p->next[id]==NULL)
{
q=(Tree*)malloc(sizeof(Tree));
q->v=1;//初始为1
for(int j=0;j<MAX;j++)
{
q->next[j]=NULL;
}
p->next[id]=q;
p=p->next[id];
}
else
{
p->next[id]->v++;
p=p->next[id];
}
}
}
int findTree(char *str)
{//查找
int len=strlen(str);
Tree *p=root;
for(int i=0;i<len;i++)
{
int id=str[i]-'a';
p=p->next[id];
if(p==NULL)//若是空树返回0
return 0;
}
return p->v;//返回以此串为前缀的字符串数目
}
int dealTree(Tree *T)
{//释放空间
if(T==NULL)
return 0;
for(int i=0;i<MAX;i++)
{
if(T->next[i]!=NULL)
dealTree(T->next[i]);
}
free(T);
return 0;
}
void init()
{
root=(Tree *)malloc(sizeof(Tree));
root->v=1;
for(int i=0;i<MAX;i++)
root->next[i]=NULL;
return;
}
int main()
{
init();//初始化根节点
char str[10];
while(gets(str)&&str[0]!='\0')
{
careTree(str);//插入建树
}
while(~scanf("%s",str))
{
printf("%d\n",findTree(str));
}
dealTree(root);//释放空间,这道题有无都可
return 0;
}
数组字典树实现:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
int next[26];
int v;//字母出现的次数
void init(){//初始化
v=0;
//数组赋值视情况而定,查前缀赋0
//赋-1出错
memset(next,0,sizeof(next));
}
};
struct node L[1000000];
int tot;//总结点数
void add(char a[])
{//建树
int now=0;
int len=strlen(a);
for(int i=0;i<len;i++)
{
int tmp=a[i]-'a';
if(L[now].next[tmp]==0)
{//不存在建立新节点
int x=tot++;
L[x].init();
L[now].next[tmp]=x;
}
now=L[now].next[tmp];
L[now].v+=1;//记录字母出现的次数
}
}
int query(char a[])
{//查询
int now=0;
int len=strlen(a);
for(int i=0;i<len;i++)
{
int tmp=a[i]-'a';
int x=L[now].next[tmp];
if(x==0) return 0;
now=x;
}
return L[now].v;
}
int main()
{
char str[10];
memset(&L[0], 0, sizeof(node));//每次清零
tot=1;
while(gets(str)&&str[0]!='\0')
{
add(str);//插入建树
}
while(~scanf("%s",str))
{//查询
printf("%d\n",query(str));
}
return 0;
}