字典树入门 统计难题

统计难题   

http://acm.hdu.edu.cn/showproblem.php?pid=1251

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 65739    Accepted Submission(s): 22659


Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
 

 

Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.
 

 

Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 

 

Sample Input
banana band bee absolute acm ba b band abc
 

 

Sample Output
2 3 1 0
 
字典树:用来查相同前缀的单词书数,第一个是用指针的做法;用指针建树;先是一个空的总根节点,然后是对应26个字母的支,有对应的字母就伸出这个枝,没有就不伸出这个枝;
           它可以根据需要来伸出枝;也可以根据不同的情况有更多的枝;可以加上其他字符和大小写;
            把这些字符用树的方式储存易于查询和删除;求前缀相同的的字符的个数,可以把前缀作为它的根节点,则前缀相同,则根节点相同;在根节点上记录分支的数量;
则是同一根节点字符串的数量,则是同一前缀字符串的数量;
 
//用指针的做法;https://blog.csdn.net/qq_36172505/article/details/76887211
#include<cstdio> #include<cstring> using namespace std; struct node{ node *next[26];//定义26个结构体指针,用来指向可能存在的分支; int cnt;//用于记录该节点分支的数量; node(){//结构体的初始化; cnt=0; memset(next,0,sizeof(next)); } }; node *root=NULL;//定义一个空的结构体指针作为总的根; void buildtree(char *s){//建树; node *p=root;//定义一个结构体指针,先指向root; int l=strlen(s); for(int i=0;i<l;i++){ if(p->next[s[i]-'a']==NULL){//判断该子根是否当前存在; p->next[s[i]-'a']=new node;//不存在就分配一个node型的内存使之存在; } p=p->next[s[i]-'a'];//指针指向该节点,并由该节点向下延伸;同一个字符串在树里也是串在一起的,
//因此同一个字符串是由根节点一直伸到枝顶,p则是一个动态的指向,表示从哪里开始延伸; p
->cnt++;//在一个节点上的一次操作会增加该节点一个分支; } } void findtree(char *s){ node *p=root; int l=strlen(s); for(int i=0;i<l;i++){ if(p->next[s[i]-'a']==NULL){//由上面可以看出所有有效地节点都被分了内存,没有分内存,说明不存在; printf("0\n"); return; } p=p->next[s[i]-'a'];//公共整个字符串,要把整个字符串作为根节点; } printf("%d\n",p->cnt);//输出该根节点对应的分支; return; } int main(){ char a[15]; root=new node;//为该指针分配空间; while(gets(a)){ if(strcmp(a,"")==0){//判断字符串是否为空; break; }else{ buildtree(a);//将字符串存在树内; } } while(gets(a)){ findtree(a);//查询; } return 0; }

 

 

//数组;https://blog.csdn.net/qq_38891827/article/details/80532462
#include<cstdio> #include<cstring> using namespace std; const int maxn=2e6+3; int tree[maxn][30];//总的节点数,和每个节点的总的分支数;tree[i][j]表示第i个节点的第j个枝; int sum[maxn];//记录该节点经过的次数,即为分支的个数; int tot;//用于记录节点数; void insert_(char *s){ int len=strlen(s); int root=0; for(int i=0;i<len;i++){ if(tree[root][s[i]-'a']==0){ tree[root][s[i]-'a']=++tot; } sum[tree[root][s[i]-'a']]++; root=tree[root][s[i]-'a']; } return; } int find_(char *s){ int len=strlen(s); int root=0; for(int i=0;i<len;i++){ if(tree[root][s[i]-'a']==0){ return 0; } root=tree[root][s[i]-'a']; } return sum[root]; } int main(){ tot=0; char a[25]; while(gets(a)){ if(strcmp(a,"")==0){ break; } insert_(a); } while(scanf("%s",a)!=EOF){ printf("%d\n",find_(a)); } return 0; }

 

转载于:https://www.cnblogs.com/qqshiacm/p/11181919.html

好的,下面是C语言实现的字典树词频统计代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_WORD_LEN 100 // 单词最大长度 // 字典树节点结构体 typedef struct TrieNode { int count; // 记录单词出现次数 struct TrieNode* next[26]; // 指向下一个字符的指针数组 } TrieNode; // 创建新的字典树节点 TrieNode* newTrieNode() { TrieNode* node = (TrieNode*)malloc(sizeof(TrieNode)); node->count = 0; memset(node->next, 0, sizeof(node->next)); return node; } // 将单词插入字典树 void insertWord(TrieNode* root, char* word) { TrieNode* node = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = tolower(word[i]) - 'a'; // 转换为小写字母后计算下标 if (node->next[index] == NULL) { node->next[index] = newTrieNode(); } node = node->next[index]; } node->count++; } // 统计单词出现次数 int countWords(TrieNode* root, char* word) { TrieNode* node = root; int len = strlen(word); for (int i = 0; i < len; i++) { int index = tolower(word[i]) - 'a'; // 转换为小写字母后计算下标 if (node->next[index] == NULL) { return 0; } node = node->next[index]; } return node->count; } int main() { TrieNode* root = newTrieNode(); char filename[100]; printf("请输入要统计的文本文件名:"); scanf("%s", filename); FILE* fp = fopen(filename, "r"); if (fp == NULL) { printf("文件打开失败!\n"); return 0; } char word[MAX_WORD_LEN]; while (fscanf(fp, "%s", word) != EOF) { insertWord(root, word); } fclose(fp); printf("请输入要查询的单词(输入quit结束查询):\n"); while (1) { scanf("%s", word); if (strcmp(word, "quit") == 0) { break; } printf("%s: %d\n", word, countWords(root, word)); } return 0; } ``` 这份代码可以读取一个文本文件,将其中的单词插入字典树中,并且可以查询某个单词在文本中出现的次数。在插入单词和查询单词时,会将单词转换为小写字母后再进行操作,这样可以避免大小写不同的单词被算作不同的单词。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值