最近在上计算机应用编程,老师给了一个大小为900MB的含20000000行邮箱地址的文件。 然后再给出了1000条查询数据,让你用字典树建树然后查询是否出现过。

试了下普通的tire树,特意用二进制写了下,结果才建了300000的时候就快用了2G内存,根本不行。

后面学习了下 PAT trie,发现确实是好东西,已经几乎达到最优内存了,如果有N个记录,那么只需要2*N个节点即可建成字典树。

算法的关键在于先将记录用一串二进制位表示,然后在建树的时候只在一些具有区别作用的二进制位进行节点分裂。

具体见http://hxraid.iteye.com/blog/615295,这篇博客讲的比较详细。

这里给出我用C++实现的代码。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
using namespace std;
#define MAXLEN 1000000000LL
#define N 20020000
struct node
{
int l,r;
int pos;
bool flag;//用来标记是否是叶子节点
int end_point;//指向叶子节点.
}g[*N]; char saveword[MAXLEN];
int word_pos[N];
short int word_len[N];
int n;
char str[];
int len;
int cnt;
char qest[][];
bool flag_ans[]; void build_tree(int s,int head)
{
if(g[head].flag==)//表示叶子结点
{
int tn=g[head].end_point;
int num=(s>>);
int other=(s&);
int ta,tb;
while()
{
if(num>=len) break;
ta=(str[num]&(<<(-other)) );
tb=(saveword[(word_pos[tn]+num)]&(<<(-other)));
if( ta!=tb )
{
//开始分裂
g[cnt]=g[head];
cnt++;
g[head].flag=;
g[head].pos=(num<<)+other;
if(tb==)
g[head].l=cnt-;
else g[head].r=cnt-;
g[cnt].end_point=n;
g[cnt].flag=;
cnt++;
if(ta!=)
g[head].r=cnt-;
else g[head].l=cnt-;
break;
}
other++;
if(other==)
{
num++;
other=;
}
}
}
else
{
int tn=g[head].end_point;
int tpos=g[head].pos;
int num;
int other;
int ta,tb;
for(int i=s;i<tpos;i++)
{
num=(i>>);
other=(i&);
ta=(str[num]&(<<(-other)) );
tb=(saveword[(word_pos[tn]+num)]&(<<(-other)));
if(ta!=tb)//ta!=tb
{
g[cnt]=g[head];
cnt++;
g[head].flag=;
g[head].pos=i;
if(tb!=)
g[head].r=cnt-;
else g[head].l=cnt-;
g[cnt].flag=;
g[cnt].end_point=n;
cnt++;
if(ta!=) g[head].r=cnt-;
else g[head].l=cnt-;
return ;
}
}
num=(tpos>>);
other=(tpos&);
ta=(str[num]&(<<(-other)) );
if(ta==)
{
build_tree(tpos+,g[head].l);
}
else build_tree(tpos+,g[head].r);
}
} int check_tree(int s)
{
if(g[s].flag==)
{
int tn=g[s].end_point;
if(len!=word_len[tn]) return ;
for(int i=;i<len;i++)
{
if(str[i]!=saveword[ word_pos[tn]+i ]) return ;
}
return ;
}
int tpos=g[s].pos;
int num=(tpos>>);
int other=(tpos&);
int ta;
ta=(str[num]&(<<(-other)) );
if(ta!=) return check_tree(g[s].r);
else return check_tree(g[s].l);
} void check()
{
//freopen("G:\\session1\\checklist.dat","r",stdin);
//cin>>T;
//getchar(); //int ansans=0;
for(int i=;i<;i++)
{
strcpy(str,qest[i]);
len=strlen(str);
str[len]='#';
len++;
str[len]=;
for(int j=;j<len;j++)
{
if(str[j]>='A'&&str[j]<='Z')
str[j]=str[j]-'A'+'a';
}
int sign1=check_tree();
//ansans+=sign1;
if(sign1==)
flag_ans[i]=;
//if(sign1==1) printf("%s\n",str);
//T--;
//if(T==0) break;
}
} int main()
{
freopen("checklist.dat","r",stdin);
freopen("checkedresult.dat","w",stdout);
int tcnt=;
while(scanf("%s",qest[tcnt])!=EOF) tcnt++;
//printf("%d\n",tcnt);
freopen("emaillist.dat","r",stdin);
//int T;
//cin>>T;
//getchar();
n=;
cnt=;
int first_flag=;
int tmp_pos=;
int cntt=;
while(scanf("%s",str)!=EOF)
{
cntt++;
if(cntt==)
{
char tstr[];
strcpy(tstr,str);
check();
cnt=;
n=;
first_flag=;
tmp_pos=;
strcpy(str,tstr);
}
word_pos[n]=tmp_pos;
len=strlen(str);
str[len]='#';
len++;
word_len[n]=len;
for(int i=;i<len;i++)
{
if(str[i]>='A'&&str[i]<='Z')
str[i]=str[i]-'A'+'a';
saveword[tmp_pos++] = str[i];
}
//然后就是构树了
if(first_flag==)
{
first_flag=;
g[].flag=;//为n号叶子结点。
g[].end_point=n;
cnt++;
}
else
{
build_tree(,);
}
n++;
//if(n%100000==0) printf("%d\n",n); //T--;
//if(T==0) break;
}
check();
int ansans=;
for(int i=;i<;i++)
{
if(flag_ans[i]==)
printf("yes\n");
else printf("no\n");
ansans+=flag_ans[i];
}
printf("%d\n",ansans);
return ;
}

PAT trie的更多相关文章

  1. Leetcode: Implement Trie (Prefix Tree) && Summary: Trie

    Implement a trie with insert, search, and startsWith methods. Note: You may assume that all inputs a ...

  2. uva 1401 dp+Trie

    http://uva.onlinejudge.org/index.php? option=com_onlinejudge&Itemid=8&page=show_problem& ...

  3. CF #Manthan, Codefest 16 C. Spy Syndrome 2 Trie

    题目链接:http://codeforces.com/problemset/problem/633/C 大意就是给个字典和一个字符串,求一个用字典中的单词恰好构成字符串的匹配. 比赛的时候是用AC自动 ...

  4. 可持久化 trie 的简单入门

    可持久化 $trie$  ....又是一个表里不一的东西..... 可持久化 $trie$  的介绍: 和主席树类似的,其实可持久化就是体现在前缀信息的维护上(搞不懂这怎么就叫做可持久化了...) $ ...

  5. poj_3987 Trie图

    题目大意 有N个病毒,病毒由A-Z字母构成,N个病毒各不相同.给出一段程序P,由A-Z字母构成,若病毒在在程序P或者P的逆转字符串P'中存在,则该程序P被该病毒感染.求出程序P被多少种病毒感染. 题目 ...

  6. 后缀树(Suffix Trie)子串匹配结构

    Suffix Trie 又称后缀Trie或后缀树.它与Trie树的最大不同在于,后缀Trie的字符串集合是由指定字符串的后缀子串构成的.比如.完整字符串"minimize"的后缀子 ...

  7. 标准Trie、压缩Trie、后缀Trie

    ref : https://dsqiu.iteye.com/blog/1705697 1.Trie导引 Trie树是一种基于树的数据结构,又称单词查找树.前缀树,是一种哈希树的变种.应用于字符串的统计 ...

  8. luoguP6623 [省选联考 2020 A 卷] 树(trie树)

    luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...

  9. 《转载》PAT 习题

    博客出处:http://blog.csdn.net/zhoufenqin/article/details/50497791 题目出处:https://www.patest.cn/contests/pa ...

随机推荐

  1. [iOS]在NavigationController中的ScrollView中的子视图都会下移64个像素

    情况是这种: 我有一个UINavigationController,设置为self.window的root视图, 然后有一个UIVIewController是UINavigtionController ...

  2. javascript - 实现jquery类似的$调用方法

    var $ = { name: function (name) { return name; }, age: function (age) { return age; }, numCount: fun ...

  3. Python基础--人们一些最爱的标准库(random time)

    Python继续! random 包括返回随机数的函数. 这里跟C++一样,产生的是伪随机数,并非全然随机数. random中一些重要的函数: random() 返回0<n<=1的随机数n ...

  4. python机器学习-逻辑回归

    1.逻辑函数 假设数据集有n个独立的特征,x1到xn为样本的n个特征.常规的回归算法的目标是拟合出一个多项式函数,使得预测值与真实值的误差最小: 而我们希望这样的f(x)能够具有很好的逻辑判断性质,最 ...

  5. 使用node.js 文档里的方法写一个web服务器

    刚刚看了node.js文档里的一个小例子,就是用 node.js 写一个web服务器的小例子 上代码 (*^▽^*) //helloworld.js// 使用node.js写一个服务器 const h ...

  6. Asp.net 数据库依赖那些事

    声明:本文为作者原创文章,转载请注明出处 https://www.cnblogs.com/MaMaNongNong/p/8904022.html 问题背景: 最近做一个非常简单的功能,就是使用ajax ...

  7. 606. Construct String from Binary Tree 【easy】

    606. Construct String from Binary Tree [easy] You need to construct a string consists of parenthesis ...

  8. match函数

    match(s, r [, a]) Return the position in s where the regular expression r occurs, or 0 if r is not p ...

  9. Python内置函数之chr()

    参数是一个整型对象: chr(integer) 返回整型对应的Unicode字符对象. 例子: >>> chr() '\x0c' >>> chr() 'ⲓ' > ...

  10. Crypto++库安装、测试

    项目中需要使用到C++加密解密库,选择了Crypto++这个开源库,于是先安装并写一个小例子试试 一.下载 网址:http://www.cryptopp.com/#download 二.打开项目 下载 ...