字典树:
字典树 即Tire树,以一个空的头结点分若干的分支,来存放数据,虽浪费了大量内存,但是查找速度非常快。
字典树 即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); root = NULL;
}
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;
}