ACM 字典树 Phone List & Hat’s Words

港控/mmm° 2022-06-12 09:42 287阅读 0赞

字典树:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。

典型应用:统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

基本性质:

1.根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3.每个节点的所有子节点包含的字符都不相同。

基本模板:(来自百度百科)

  1. #define MAX 26//字符集大小
  2. typedef struct TrieNode
  3. {
  4. int nCount;//记录该字符出现次数
  5. struct TrieNode* next[MAX];
  6. }TrieNode;
  7. TrieNode Memory[1000000];
  8. int allocp=0;
  9. /*初始化*/
  10. void InitTrieRoot(TrieNode* *pRoot)
  11. {
  12. *pRoot=NULL;
  13. }
  14. /*创建新结点*/
  15. TrieNode* CreateTrieNode()
  16. {
  17. int i;
  18. TrieNode *p;
  19. p=&Memory[allocp++];
  20. p->nCount=1;
  21. for(i=0;i<MAX;i++)
  22. {
  23. p->next[i]=NULL;
  24. }
  25. return p;
  26. }
  27. /*插入*/
  28. void InsertTrie(TrieNode* *pRoot,char *s)
  29. {
  30. int i,k;
  31. TrieNode*p;
  32. if(!(p=*pRoot))
  33. {
  34. p=*pRoot=CreateTrieNode();
  35. }
  36. i=0;
  37. while(s[i])
  38. {
  39. k=s[i++]-'a';//确定branch
  40. if(!p->next[k])
  41. p->next[k]=CreateTrieNode();
  42. else
  43. p->next[k]->nCount++;
  44. p=p->next[k];
  45. }
  46. }
  47. //查找
  48. int SearchTrie(TrieNode* *pRoot,char *s)
  49. {
  50. TrieNode *p;
  51. int i,k;
  52. if(!(p=*pRoot))
  53. {
  54. return0;
  55. }
  56. i=0;
  57. while(s[i])
  58. {
  59. k=s[i++]-'a';
  60. if(p->next[k]==NULL) return 0;
  61. p=p->next[k];
  62. }
  63. return p->nCount;
  64. }

HDU 1671 Phone List

20170720221601813

20170720221610429

题目大意:(例题带入)有2组数据,第一组数据有3个电话号码,问是否存在一个号码是另一个的前缀,若存在则不合适,输出NO。

思路:字典树,在建树的时候直接判断了…

  1. #include <iostream>
  2. #define MAX 10
  3. using namespace std;
  4. bool flag;
  5. typedef struct Trie_Node
  6. {
  7. bool isphone;
  8. struct Trie_Node *next[MAX];
  9. }Trie;
  10. void insert(Trie *root,char *phone)
  11. {
  12. Trie *p=root;
  13. while(*phone!='\0')
  14. {
  15. if(p->next[*phone-48]==NULL)
  16. {
  17. Trie *temp=(Trie *)malloc(sizeof(Trie));
  18. temp->isphone=false;
  19. for(int i=0;i<MAX;i++)
  20. temp->next[i]=NULL;
  21. p->next[*phone-48]=temp;
  22. }
  23. if(p->isphone==true)
  24. flag=true;
  25. p=p->next[*phone-48];
  26. phone++;
  27. }
  28. p->isphone=true;
  29. for(int i=0;i<MAX;i++)
  30. {
  31. if(p->next[i]!=NULL)
  32. {
  33. flag=true;
  34. break;
  35. }
  36. }
  37. }
  38. void del(Trie *root)
  39. {
  40. for(int i=0;i<MAX;i++)
  41. {
  42. if(root->next[i]!=NULL)
  43. del(root->next[i]);
  44. }
  45. free(root);
  46. }
  47. int main(int argc, char *argv[])
  48. {
  49. int t;
  50. scanf("%d",&t);
  51. while(t--)
  52. {
  53. int i;
  54. int n;
  55. char phone[11];
  56. Trie *root=(Trie *)malloc(sizeof(Trie));
  57. root->isphone=false;
  58. flag=false;
  59. for(i=0;i<MAX;i++)
  60. root->next[i]=NULL;
  61. scanf("%d",&n);
  62. for(i=0;i<n;i++)
  63. {
  64. scanf("%s",phone);
  65. if(flag!=true)
  66. insert(root,phone);
  67. }
  68. if(flag==true)
  69. printf("NO\n");
  70. else
  71. printf("YES\n");
  72. del(root);
  73. }
  74. return 0;
  75. }

HDU 1247 Hat’s Words

20170720221919551

题目大意:输入直到EOF结束,判断是否存在两个组合可以组成另一个字符串。

思路:先把所有字符串都存下来建树,然后从根走到每个叶子结点记下来比较。

  1. #include<iostream>
  2. #include<string.h>
  3. #include<stdlib.h>
  4. #include<stdio.h>
  5. #include<algorithm>
  6. using namespace std;
  7. const int MAX=26;
  8. typedef struct Trie_Node
  9. {
  10. bool isWord;
  11. struct Trie_Node *next[MAX];
  12. }Trie;
  13. char s[50010][50];
  14. void insert(Trie *root,char *word)
  15. {
  16. Trie *p=root;
  17. int i=0;
  18. while(word[i]!='\0')
  19. {
  20. if(p->next[word[i]-'a']==NULL)
  21. {
  22. Trie *temp=(Trie *)malloc(sizeof(Trie));
  23. for(int j=0;j<MAX;j++)
  24. temp->next[j]=NULL;
  25. temp->isWord=false;
  26. p->next[word[i]-'a']=temp;
  27. }
  28. p=p->next[word[i]-'a'];
  29. i++;
  30. }
  31. p->isWord=true;
  32. }
  33. bool search(Trie *root,char *word)
  34. {
  35. Trie *p=root;
  36. for(int i=0;word[i]!='\0';i++)
  37. {
  38. if(p->next[word[i]-'a']==NULL)
  39. return false;
  40. p=p->next[word[i]-'a'];
  41. }
  42. return p->isWord;
  43. }
  44. void del(Trie *root)
  45. {
  46. for(int i=0;i<MAX;i++)
  47. {
  48. if(root->next[i]!=NULL)
  49. del(root->next[i]);
  50. }
  51. free(root);
  52. }
  53. int main()
  54. {
  55. int i,j;
  56. int cnt=0;
  57. char str[50];
  58. Trie *root=(Trie *)malloc(sizeof(Trie));
  59. for(i=0;i<MAX;i++)
  60. root->next[i]=NULL;
  61. root->isWord=false;
  62. while(scanf("%s",s[cnt])!=EOF)
  63. {
  64. insert(root,s[cnt++]);
  65. }
  66. for(i=0;i<cnt;i++)
  67. {
  68. int len=strlen(s[i]);
  69. for(j=1;j<len-1;j++)
  70. {
  71. char temp1[50]={'\0'};
  72. char temp2[50]={'\0'};
  73. strncpy(temp1,s[i],j);
  74. strncpy(temp2,s[i]+j,len-j);
  75. if(search(root,temp1)&&search(root,temp2))
  76. {
  77. printf("%s\n",s[i]);
  78. break;
  79. }
  80. }
  81. }
  82. del(root);
  83. return 0;
  84. }

发表评论

表情:
评论列表 (有 0 条评论,287人围观)

还没有评论,来说两句吧...

相关阅读