字典树:
字典树 即Tire树,以一个空的头结点分若干的分支,来存放数据,虽浪费了大量内存,但是查找速度非常快。
匹配 时间复杂度 O(n) n = strlen(a);
字典树分 3步,建树、插入、查找
当然有时候,建树的选择是很重要的一点,尽量本着少往字典树上添加节点的原则,容易爆!!!
列入下面这题,用m建树,n来查找,即可AC,如果用n来建树,就会爆内存,所以建树的选择是很重要的一点
给定n个字符串,m个字符串,判断n中有多少个 是与m不一样的字符串。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> const int N = 20010; using namespace std; struct node{ int flag;//标记作用 node *next[26]; }; int n,m; struct node *Creat() //建树 { node *p = new node; for(int i = 0;i<26;i++) { p->next[i] = NULL; } p->flag = 0; return p; } void INsert(node *root,char *b) //插入 { int num; int len = strlen(b); node *p = root; for(int i = 0;i<len;i++) { if(b[i]>='A' && b[i]<='Z') num = b[i]-'A'; else num = b[i]-'a'; if(p->next[num]==NULL)//如果为空,在当前节点的基础上在建树 { p->next[num] = Creat(); } p = p->next[num]; //指针移动到下一个节点 } p->flag = 1; //插入完成标记为1 } int Search(node *root,char *b) //查找 { node *p = root; int num; int len = strlen(b); for(int i = 0;i<len;i++) { if(b[i]>='A' && b[i]<='Z') num = b[i] - 'A'; else num = b[i]-'a'; if(p->next[num]==NULL) //不存在 return 0; p = p->next[num]; } if(p->flag==1) //找到 { p->flag = 0;//预防重复查找 return 1; } return 0; } void FREE(struct node*root) { for(int i = 0;i<n;i++) { if(root->next[i]!=NULL) { FREE(root->next[i]); } } free(root); } int main() { char a[N][50],s[50]; node *p; while(scanf("%d",&n),n) { scanf("%d",&m); p = Creat(); for(int i = 0;i<n;i++) { scanf("%s",a[i]); } for(int i = 0;i<m;i++) { scanf("%s",s); INsert(p,s); } int sum = 0; for(int i = 0;i<n;i++) { sum += Search(p,a[i]); } printf("%d\n",n-sum); FREE(p); } return 0; }
时间: 2024-10-21 00:46:09