Java实现字典树处理海量数据查重
问题背景:
给定两个含海量字符串的文件file1和file2,要求找出file2中哪些字符串存在于file1。处理方法很多,这里主要实现一下字典树的方法
字典树数据结构:
废话少说,直接看图(网上盗的...)
被标红的节点表示从根节点到该节点路径上的单词依次从上至下组成的字符串已经出现过。(节点内的值不重要,重要的是节点到其孩子节点边上的值)
在我的代码里,字典树每个节点数据结构如下:
class Node{boolean v;Node[] children = new Node[NUM_CHILD]; // 每个Node有5个孩子 每个孩子都是Node
}
详细代码:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Random;public class DictTree {private File f = new File("words.txt"), test = new File("test.txt");private Writer writer = null;private Reader reader = null;private final int NUM_CHILD = 5; //每个节点的孩子数目private final int NUM_TRAIN_WORD = 10000; // 用于构造字典树的单词数目private final int NUM_TEST_WORD = 10; // 用于检测的单词数目private final int MAX_LENGTH = 5; // 每个单词的最大长度private class Node{boolean v; // 用于标记从根节点到该节点路径上的字符组成的字符串是否已经出现过Node[] children = new Node[NUM_CHILD]; // 每个Node有5个孩子 每个孩子都是Node}// 产生用于构造字典树的单词集 以及 用于测试字典树的单词集 写入文件private void genWords() throws IOException {try {writer = new BufferedWriter(new FileWriter(f));Random random = new Random();// 随机产生NUM_TRAIN_WORD个单词 每个单词的长度在[1,MAX_LENGTH] 每个单词的字母为['a', 'a' + NUM_CHILD - 1]for (int i = 0; i < NUM_TRAIN_WORD; i++) {int len = random.nextInt(MAX_LENGTH) + 1; // 随机获得单词的长度 +1保证不会产生空串StringBuilder sb = new StringBuilder();for (int k = 0; k < len; k++) {sb.append((char)('a' + random.nextInt(NUM_CHILD)));}writer.write(sb.toString() + "\n");}writer.close();writer = new BufferedWriter(new FileWriter(test));// 随机产生NUM_TEST_WORD个单词用于检测NUM_TEST_WORD个单词哪些在test文件之中 每个单词的长度在[1,MAX_LENGTH] 每个单词的字母为['a','a' + NUM_CHILD - 1]for (int i = 0; i < NUM_TEST_WORD; i++) {int len = random.nextInt(MAX_LENGTH) + 1; // 随机获得单词的长度 +1保证不会产生空串StringBuilder sb = new StringBuilder();for (int k = 0; k < len; k++) {sb.append((char)('a' + random.nextInt(NUM_CHILD)));}writer.write(sb.toString() + "\n");}writer.close();} catch (Exception e) {e.printStackTrace();}}// 根据文件内的字符串 生成字典树 返回字典树根节点private Node generateTree() throws IOException {reader = new BufferedReader(new FileReader(f));char[] target = new char[NUM_TRAIN_WORD * (MAX_LENGTH + 1)];reader.read(target); // 将文件内容读入字符数组target// 先使用trim去除字符串左右两边的空白字符String[] splits = new String(target).trim().split("\n"); // 从文件获取到所有的单词Node root = new Node(); // 创建树节点 树节点的值不重要for (String str : splits) {Node r = root;for (int i = 0; i < str.length(); i++) {char c = str.charAt(i);if (i == str.length() - 1) { // 是最后一个字符 则需要将该字符的v置为true 表明从根节点到该节点所经历的字符是一个已出现过的串if (r.children[c - 'a'] == null) // 该字符之前不存在r.children[c - 'a'] = new Node();r.v = true;} else {if (r.children[c - 'a'] == null) // 该字符之前不存在r.children[c - 'a'] = new Node();r = r.children[c - 'a'];}}}reader.close();return root;}// 检测test.txt文件中哪些字符串存在于words.txtprivate void test(Node root) throws IOException {reader = new BufferedReader(new FileReader(test));char[] target = new char[NUM_TEST_WORD * (MAX_LENGTH + 1)];reader.read(target);String[] splits = new String(target).trim().split("\n"); // 从文件获取到所有的单词for (String s : splits) {System.out.println(s + ":" + testExist(root, s));}}// 对于一个字符串s,判断其在字典树中是否存在private boolean testExist(Node root, String s) {char[] cs = s.toCharArray();Node r = root;for (int i = 0; i < cs.length; i++) {if (r.children[cs[i] - 'a'] == null)return false;if (i == cs.length - 1 && r.v)return true;r = r.children[cs[i] - 'a'];}return false; // 字典树中只存在以s为前缀的单词 并不存在s}public static void main(String[] args) throws IOException {DictTree dictTree = new DictTree();dictTree.genWords();dictTree.test(dictTree.generateTree());}}
测试效果:
Java实现字典树处理海量数据查重相关推荐
- Java实现字典树 Trie
Java实现字典树 Trie 一.字典树介绍 二.Trie实现以及基本的插入查询操作 数组实现: HashMap实现: Trie插入(这里都以数组实现为例): Trie查询: 三.相关例题: 1.le ...
- 基础数据结构(二):字典树、并查集、堆、哈希表、字符串的哈希方式、STL的常见容器及其接口
文章目录 一.字典树Trie 1 原理 2 Trie字符串统计 3 [LeetCode 208. 实现 Trie (前缀树)](https://leetcode-cn.com/problems/imp ...
- 经典算法题:字典树、并查集、单调栈、二分、带标记函数dp、树、全排列、字符串问题等常用算法
0. Tips 1. 位运算 如何枚举一个二进制状态数字k的子集, 方法就是针对中的二进制为1的位开始进行减法,判断数字k的二进制子集, 像枚举(2^k-1) ~ 0一样枚举其子集: int sub ...
- Day10 堆排序、模拟堆 trie树(字典树) 并查集
堆呢就是一棵树完全二叉树... 小根堆的话,根节点就是最小值 维护堆只有两个操作 up(k) down(k) cnt是堆的大小 建堆的话只需要把前n/2的数down下来就ok 复杂度是小于O(n) 的 ...
- Java Trie字典树,前缀树
Trie查询每个条目的时间复杂度,和字典中一共有多少条无关. 时间复杂度为O(W) w为查询单词的长度 import java.util.TreeMap;public class Trie {priv ...
- java trie_java字典树(Trie)实现中文模糊匹配
package com.xq.algorithm; import java.io.BufferedReader; import java.io.IOException; import java.uti ...
- 用java设计一个文件查重程序,输入两个文本文件,输出两个文本文件的重复率(最长公共子序列的应用)...
你可以使用java代码来设计一个文件查重程序.首先,你需要读取两个文本文件的内容,将它们存储在字符串变量中.然后,你可以使用最长公共子序列(LCS)算法来计算两个字符串的重复率. LCS算法的实现方法 ...
- 用Python实现字典树(Trie)与双数组字典树(DATrie)
1. 字典树(Trie) 假如我们把字典中的词以记录的形式(无序)存入数据库中.现给定一串字符,要查找该字符串是否为字典中的词.因为数据库中的记录是无序的,所以,最朴素的方法就逐记录匹配.此方法简单, ...
- 字典树(Trie)的java实现
一.定义 字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:利用 ...
最新文章
- JAVA面试相关基础知识
- AC自动机算法及模板
- 网页设计千千万,网站建设万万千
- 怎么证明权重不相同的加权无向图的最小生成树是唯一的 (图论)
- Spring Security系列教程解决Spring Security环境中的跨域问题
- (二)SpringBoot 整合 JPA
- macbook 下载时睡眠_MacBook进入睡眠状态时如何自动使其静音
- 机房收费系统合作版(五)——初识托付
- RGB数据保存为BMP图片
- opencv 图像平滑、图像模糊函数的使用
- armv6 armv7 armv7s架构的区别
- 轻松学会硬盘还原卡的安装和使用
- 【学习】无刷直流电机的基本结构及工作原理
- Scoks5 一键搭建脚本,解决nolanjdc被限制IP
- ICH1/ICH2/ICH3/ICH4/ICH5/ICH6/ICH7/ICH8/ICH9的区别和联系
- Windows提权基本原理,各位表哥了解下!
- 侍魂微信新服务器,侍魂手游2019年3月23日微信问答试炼答案
- 文件服务器之一:NFS 服务器
- python的os删除文件或者文件夹
- 《Python语言程序设计》王恺 王志 李涛 机械工业出版社 第6章 字符串 课后习题答案【强烈推荐】