广告
返回顶部
首页 > 资讯 > 精选 >Java中怎么实现一个双数组Trie树
  • 557
分享到

Java中怎么实现一个双数组Trie树

2023-06-17 09:06:20 557人浏览 泡泡鱼
摘要

本篇文章给大家分享的是有关Java中怎么实现一个双数组Trie树,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。对于插入字符串,如果有一个字符串是另一个字符串的子串的话,我是将结

本篇文章给大家分享的是有关Java中怎么实现一个双数组Trie树,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

对于插入字符串,如果有一个字符串是另一个字符串的子串的话,我是将结束符也作为一条边,产生一个新的结点,这个结点新节点的Base我置为0

所以一个字符串结束也有2中情况:一个是Base值为负,存储剩余字符(可能只有一个结束符)到Tail数组;另一个是Base为0。

所以在查询的时候要考虑一下这两种情况

对于***种冲突(论文中的Case 3),可能要将Tail中的字符串取出一部分,作为边放到索引中。论文是使用将尾串左移的方式,我的方式直接修改Base值,而不是移动尾串。

下面是java实现的代码,可以处理相同字符串插入,子串的插入等情况

   import java.util.ArrayList;  import java.util.HashMap;  import java.util.Map;  import java.util.Arrays;    public class DoubleArrayTrie {      final char END_CHAR = '\0';      final int DEFAULT_LEN = 1024;      int Base[]  = new int [DEFAULT_LEN];      int Check[] = new int [DEFAULT_LEN];      char Tail[] = new char [DEFAULT_LEN];      int Pos = 1;      Map<Character ,Integer> CharMap = new HashMap<Character,Integer>();      ArrayList<Character> CharList = new ArrayList<Character>();            public DoubleArrayTrie()      {          Base[1] = 1;                    CharMap.put(END_CHAR,1);          CharList.add(END_CHAR);          CharList.add(END_CHAR);          for(int i=0;i<26;++i)          {              CharMap.put((char)('a'+i),CharMap.size()+1);              CharList.add((char)('a'+i));          }                }      private void Extend_Array()      {          Base = Arrays.copyOf(Base, Base.length*2);          Check = Arrays.copyOf(Check, Check.length*2);      }            private void Extend_Tail()      {          Tail = Arrays.copyOf(Tail, Tail.length*2);      }            private int GetCharCode(char c)      {          if (!CharMap.containsKey(c))          {              CharMap.put(c,CharMap.size()+1);              CharList.add(c);          }          return CharMap.get(c);      }      private int CopyToTailArray(String s,int p)      {          int _Pos = Pos;          while(s.length()-p+1 > Tail.length-Pos)          {              Extend_Tail();          }          for(int i=p; i<s.length();++i)          {              Tail[_Pos] = s.charAt(i);              _Pos++;          }          return _Pos;      }            private int x_check(Integer []set)      {          for(int i=1; ; ++i)          {              boolean flag = true;              for(int j=0;j<set.length;++j)              {                  int cur_p = i+set[j];                  if(cur_p>= Base.length) Extend_Array();                  if(Base[cur_p]!= 0 || Check[cur_p]!= 0)                  {                      flag = false;                      break;                  }              }              if (flag) return i;          }      }            private ArrayList<Integer> GetChildList(int p)      {          ArrayList<Integer> ret = new ArrayList<Integer>();          for(int i=1; i<=CharMap.size();++i)          {              if(Base[p]+i >= Check.length) break;              if(Check[Base[p]+i] == p)              {                  ret.add(i);              }          }          return ret;      }            private boolean TailContainString(int start,String s2)      {          for(int i=0;i<s2.length();++i)          {              if(s2.charAt(i) != Tail[i+start]) return false;          }                    return true;      }      private boolean TailMatchString(int start,String s2)      {          s2 += END_CHAR;          for(int i=0;i<s2.length();++i)          {              if(s2.charAt(i) != Tail[i+start]) return false;          }          return true;      }                  public void Insert(String s) throws Exception      {          s += END_CHAR;                    int pre_p = 1;          int cur_p;          for(int i=0; i<s.length(); ++i)          {              //获取状态位置              cur_p = Base[pre_p]+GetCharCode(s.charAt(i));              //如果长度超过现有,拓展数组              if (cur_p >= Base.length) Extend_Array();                            //空闲状态              if(Base[cur_p] == 0 && Check[cur_p] == 0)              {                  Base[cur_p] = -Pos;                  Check[cur_p] = pre_p;                  Pos = CopyToTailArray(s,i+1);                  break;              }else             //已存在状态              if(Base[cur_p] > 0 && Check[cur_p] == pre_p)              {                  pre_p = cur_p;                  continue;              }else             //冲突 1:遇到 Base[cur_p]小于0的,即遇到一个被压缩存到Tail中的字符串              if(Base[cur_p] < 0 && Check[cur_p] == pre_p)              {                  int head = -Base[cur_p];                                    if(s.charAt(i+1)== END_CHAR && Tail[head]==END_CHAR)    //插入重复字符串                  {                      break;                  }                                    //公共字母的情况,因为上一个判断已经排除了结束符,所以一定是2个都不是结束符                  if (Tail[head] == s.charAt(i+1))                  {                      int avail_base = x_check(new Integer[]{GetCharCode(s.charAt(i+1))});                      Base[cur_p] = avail_base;                                            Check[avail_base+GetCharCode(s.charAt(i+1))] = cur_p;                      Base[avail_base+GetCharCode(s.charAt(i+1))] = -(head+1);                      pre_p = cur_p;                      continue;                  }                  else                 {                      //2个字母不相同的情况,可能有一个为结束符                      int avail_base ;                      avail_base = x_check(new Integer[]{GetCharCode(s.charAt(i+1)),GetCharCode(Tail[head])});                                            Base[cur_p] = avail_base;                                            Check[avail_base+GetCharCode(Tail[head])] = cur_p;                      Check[avail_base+GetCharCode(s.charAt(i+1))] = cur_p;                                            //Tail 为END_FLAG 的情况                      if(Tail[head] == END_CHAR)                          Base[avail_base+GetCharCode(Tail[head])] = 0;                      else                         Base[avail_base+GetCharCode(Tail[head])] = -(head+1);                      if(s.charAt(i+1) == END_CHAR)                           Base[avail_base+GetCharCode(s.charAt(i+1))] = 0;                      else                         Base[avail_base+GetCharCode(s.charAt(i+1))] = -Pos;                                            Pos = CopyToTailArray(s,i+2);                      break;                  }              }else             //冲突2:当前结点已经被占用,需要调整pre的base              if(Check[cur_p] != pre_p)              {                  ArrayList<Integer> list1 = GetChildList(pre_p);                  int toBeAdjust;                  ArrayList<Integer> list = null;                  if(true)                  {                      toBeAdjust = pre_p;                      list = list1;                  }                                    int origin_base = Base[toBeAdjust];                  list.add(GetCharCode(s.charAt(i)));                  int avail_base = x_check((Integer[])list.toArray(new Integer[list.size()]));                  list.remove(list.size()-1);                                    Base[toBeAdjust] = avail_base;                  for(int j=0; j<list.size(); ++j)                  {                      //BUG                       int tmp1 = origin_base + list.get(j);                      int tmp2 = avail_base + list.get(j);                                            Base[tmp2] = Base[tmp1];                      Check[tmp2] = Check[tmp1];                                            //有后续                      if(Base[tmp1] > 0)                      {                          ArrayList<Integer> subsequence = GetChildList(tmp1);                          for(int k=0; k<subsequence.size(); ++k)                          {                              Check[Base[tmp1]+subsequence.get(k)] = tmp2;                          }                      }                                            Base[tmp1] = 0;                      Check[tmp1] = 0;                  }                                    //更新新的cur_p                  cur_p = Base[pre_p]+GetCharCode(s.charAt(i));                                    if(s.charAt(i) == END_CHAR)                      Base[cur_p] = 0;                  else                     Base[cur_p] = -Pos;                  Check[cur_p] = pre_p;                  Pos = CopyToTailArray(s,i+1);                  break;              }          }      }            public boolean Exists(String Word)      {          int pre_p = 1;          int cur_p = 0;                    for(int i=0;i<word.length();++i)          {              cur_p = Base[pre_p]+GetCharCode(word.charAt(i));              if(Check[cur_p] != pre_p) return false;              if(Base[cur_p] < 0)              {                  if(TailMatchString(-Base[cur_p],word.substring(i+1)))                      return true;                  return false;              }              pre_p = cur_p;          }          if(Check[Base[cur_p]+GetCharCode(END_CHAR)] == cur_p)              return true;          return false;      }            //内部函数,返回匹配单词的最靠后的Base index,      class FindStruct      {          int p;          String prefix="";      }      private FindStruct Find(String word)      {          int pre_p = 1;          int cur_p = 0;          FindStruct fs = new FindStruct();          for(int i=0;i<word.length();++i)          {              // BUG              fs.prefix += word.charAt(i);              cur_p = Base[pre_p]+GetCharCode(word.charAt(i));              if(Check[cur_p] != pre_p)              {                  fs.p = -1;                  return fs;              }              if(Base[cur_p] < 0)              {                  if(TailContainString(-Base[cur_p],word.substring(i+1)))                  {                      fs.p = cur_p;                      return fs;                  }                  fs.p = -1;                  return fs;              }              pre_p = cur_p;          }          fs.p =  cur_p;          return fs;      }            public ArrayList<String> GetAllChildWord(int index)      {          ArrayList<String> result = new ArrayList<String>();          if(Base[index] == 0)          {              result.add("");              return result;          }          if(Base[index] < 0)          {              String r="";              for(int i=-Base[index];Tail[i]!=END_CHAR;++i)              {                  r+= Tail[i];              }              result.add(r);              return result;          }          for(int i=1;i<=CharMap.size();++i)          {              if(Check[Base[index]+i] == index)              {                  for(String s:GetAllChildWord(Base[index]+i))                  {                      result.add(CharList.get(i)+s);                  }                  //result.addAll(GetAllChildWord(Base[index]+i));              }          }          return result;      }            public ArrayList<String> FindAllWords(String word)      {          ArrayList<String> result = new ArrayList<String>();          String prefix = "";          FindStruct fs = Find(word);          int p = fs.p;          if (p == -1) return result;          if(Base[p]<0)          {              String r="";              for(int i=-Base[p];Tail[i]!=END_CHAR;++i)              {                  r+= Tail[i];              }              result.add(fs.prefix+r);              return result;          }                    if(Base[p] > 0)          {              ArrayList<String> r =  GetAllChildWord(p);              for(int i=0;i<r.size();++i)              {                  r.set(i, fs.prefix+r.get(i));              }              return r;          }                    return result;      }        }

测  试

import java.io.BufferedReader;  import java.io.FileInputStream;  import java.io.IOException;  import java.io.InputStream;  import java.io.InputStreamReader;  import java.util.ArrayList;  import java.util.Scanner;   import javax.xml.crypto.Data;    public class Main {       public static void main(String[] args) throws Exception {          ArrayList<String> words = new ArrayList<String>();          BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("E:/兔子的试验学习中心[课内]/ACM大赛/ACM第四届校赛/E命令提示/words3.dic")));          String s;          int num = 0;          while((s=reader.readLine()) != null)          {              words.add(s);              num ++;          }          DoubleArrayTrie dat = new DoubleArrayTrie();                    for(String word: words)          {              dat.Insert(word);          }                    System.out.println(dat.Base.length);          System.out.println(dat.Tail.length);                    Scanner sc = new Scanner(System.in);          while(sc.hasNext())          {              String word = sc.next();              System.out.println(dat.Exists(word));              System.out.println(dat.FindAllWords(word));          }                }   }

下面是测试结果,构造6W英文单词的DAT,大概需要20秒

我增长数组的时候是每次长度增加到2倍,初始1024

Base和Check数组的长度为131072

Tail的长度为262144

Java中怎么实现一个双数组Trie树

以上就是Java中怎么实现一个双数组Trie树,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注编程网精选频道。

--结束END--

本文标题: Java中怎么实现一个双数组Trie树

本文链接: https://www.lsjlt.com/news/288290.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中怎么实现一个双数组Trie树
    本篇文章给大家分享的是有关Java中怎么实现一个双数组Trie树,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。对于插入字符串,如果有一个字符串是另一个字符串的子串的话,我是将结...
    99+
    2023-06-17
  • Vue中怎么实现一个树形组件
    Vue中怎么实现一个树形组件,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。具体如下:使用SemanticUI和vue做一个me...
    99+
    2022-10-19
  • 怎么在Java中实现一个二叉树路径
    这篇文章给大家介绍怎么在Java中实现一个二叉树路径,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。给定一个二叉树,和 目标值 = 5:  1 / \ 2 4&...
    99+
    2023-05-30
    java
  • C#中怎么实现一个递归树
    这期内容当中小编将会给大家带来有关C#中怎么实现一个递归树,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。C#递归树实现实例:从父结点加字节点,注释的是把字节点向父结点上加//将数据填充到dataTable...
    99+
    2023-06-17
  • 怎么在Vue中使用Element实现一个树列表组件
    怎么在Vue中使用Element实现一个树列表组件?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、常规树列表控件的使用众所周知,一般界面很多情况涉及到树列表的处理,如类型...
    99+
    2023-06-15
  • Echarts中怎么实现一个树形图表
    Echarts中怎么实现一个树形图表,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。树图主要用来可视化树形数据结构,是一种特殊的层次类型。实现方法,将series->t...
    99+
    2023-06-20
  • php 中怎么实现树形数组
    这篇文章给大家介绍php 中怎么实现树形数组,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。$items = array(   0 =&...
    99+
    2022-10-19
  • 怎么在Java中实现一个双向匹配分词算法
    本篇文章为大家展示了怎么在Java中实现一个双向匹配分词算法,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。正向最大匹配分词:该算法是基于分词词典实现,从字符串左侧进行分割匹配,如果词典存在则返回分割...
    99+
    2023-05-30
    java
  • JavaScript 中怎么实现一个二叉树算法
    这篇文章将为大家详细讲解有关JavaScript 中怎么实现一个二叉树算法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。二叉树和二叉搜索树介绍二叉树中的节点...
    99+
    2022-10-19
  • VB.NET中怎么实现一个控件数组
    本篇文章为大家展示了VB.NET中怎么实现一个控件数组,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Public Class CheckBoxArrClass Chec...
    99+
    2023-06-17
  • C#中怎么实现一个动态数组
    C#中怎么实现一个动态数组,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。数组的容量是固定的,但ArrayList的容量可以根据需要自动扩充。当我们修改了ArrayList的...
    99+
    2023-06-17
  • 【Java 数据结构】实现一个二叉搜索树
    目录  1、认识二叉搜索树 2、实现一个二叉搜索树 2.1 成员变量 2.2 insert 方法 2.3 search 方法  2.4 remove 方法(重点) 3、二叉搜索树总结 1、认识二叉搜索树 从字面上来看,它只比二叉树多...
    99+
    2023-09-02
    数据结构 算法 二叉搜索树
  • FineReport中树数据集怎么实现组织树报表
    FineReport中树数据集怎么实现组织树报表,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 组织树报表中由id与父id来实现组织树报表,若层级数较多时,对每个单元格设置过滤...
    99+
    2023-06-03
  • 怎么在java项目中实现一个二叉查找树算法
    今天就跟大家聊聊有关怎么在java项目中实现一个二叉查找树算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体内容如下package 查找;import edu...
    99+
    2023-05-31
    java 二叉查找树 ava
  • 怎么在java中利用数组实现一个环形队列
    本篇文章为大家展示了怎么在java中利用数组实现一个环形队列,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应用程序、分布式系...
    99+
    2023-06-14
  • Java中怎么实现一个通用组合算法
    Java中怎么实现一个通用组合算法,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Java实现通用组合算法,存在一个类似{31311133,33113330}这样的集合,经过...
    99+
    2023-06-17
  • Java怎么实现通过键盘输入一个数组
    本篇内容介绍了“Java怎么实现通过键盘输入一个数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如何通过键盘输入一个数组有时候在编写Jav...
    99+
    2023-06-29
  • HTML5 中怎么实现一个3D网络拓扑树
    这篇文章给大家介绍 HTML5 中怎么实现一个3D网络拓扑树,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 创建一个树状结构有了解过HT for Web的朋友,对树状结构数据的创建应该都不陌生,在这里我就不做深入的探讨...
    99+
    2023-06-17
  • java怎么将两个数组合并为一个数组
    在Java中,可以使用`System.arraycopy()`或`Arrays.copyOf()`方法来将两个数组合并为一个数组。方...
    99+
    2023-08-16
    java
  • Java中怎么实现一个数字时钟
    这期内容当中小编将会给大家带来有关Java中怎么实现一个数字时钟,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。代码如下:package me.socketthread;import j...
    99+
    2023-05-31
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作