提起字典我们首先想到的就是小时候使用的新华字典,字典的好处就是把大量的汉字,组织到了一本书中,安装一定的顺序方便了我们进行快速的查找。
1、给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过,以及出现的次数。
如果内存可以存储下,可以直接使用hashmap进行处理,key存储当前的单词,value存储出现的次数。时间复杂度为把单词放入的时间O(n)
2.给出n个单词和m个询问,每次询问一个前缀,回答询问是多少个单词的前缀。
可以把单词都按前缀拆分开,并全部都放到map中即可
abnormal a ab abn abno ... 都是其前缀
字典树
定义树节点
private int SIZE = 26;private TrieNode root;// 字典树的根class TrieNode // 字典树节点 { private int num;// 有多少单词通过这个节点,即由根至该节点组成的字符串模式出现的次数 private TrieNode[] son;// 所有的儿子节点 private boolean isEnd;// 是不是最后一个节点 private char val;// 节点的值 //对每一个节点的初始化 TrieNode() { num = 1; son = new TrieNode[SIZE]; isEnd = false; } }
注意这里每一个孩子节点都有26个,正好表示26个字母,只要求每一个字母的代表的数字,就可以只有孩子节点的位置。
初始化字典树
Trie() // 初始化字典树 { root = new TrieNode(); }
创建字典树
// 建立字典树 public void insert(String str) // 在字典树中插入一个单词 { if (str == null || str.length() == 0) { return; } TrieNode node = root; char[] letters = str.toCharArray();//将目标单词转换为字符数组 for (int i = 0, len = str.length(); i < len; i++) { int pos = letters[i] - 'a'; if (node.son[pos] == null) //如果当前节点的儿子节点中没有该字符,则构建一个TrieNode并复值该字符 { node.son[pos] = new TrieNode(); node.son[pos].val = letters[i]; } else //如果已经存在,则将由根至该儿子节点组成的字符串模式出现的次数+1 { node.son[pos].num++; } //孩子节点变为node节点 node = node.son[pos]; } node.isEnd = true; }
计算单词前缀的数量
前缀的数量就是当前节点前一个节点上所记录的数据的量
public int countPrefix(String prefix) { if(prefix==null||prefix.length()==0) { return-1; } TrieNode node=root; char[]letters=prefix.toCharArray(); for(int i=0,len=prefix.length(); i<len; i++) { int pos=letters[i]-'a'; if(node.son[pos]==null) { return 0; } else { node=node.son[pos]; } } return node.num; }
打印指定前缀的单词
public String hasPrefix(String prefix) { if (prefix == null || prefix.length() == 0) { return null; } TrieNode node = root; char[] letters = prefix.toCharArray(); for (int i = 0, len = prefix.length(); i < len; i++) { int pos = letters[i] - 'a'; if (node.son[pos] == null) { return null; } else { node = node.son[pos]; } } preTraverse(node, prefix); return null; }// 遍历经过此节点的单词. public void preTraverse(TrieNode node, String prefix) { if (!node.isEnd) { for (TrieNode child : node.son) { if (child != null) { preTraverse(child, prefix + child.val); } } return; } System.out.println(prefix); }
在字典树中查找一个完全匹配的单词.
public boolean has(String str) { if(str==null||str.length()==0) { return false; } TrieNode node=root; char[]letters=str.toCharArray(); for(int i=0,len=str.length(); i<len; i++) { int pos=letters[i]-'a'; if(node.son[pos]!=null) { node=node.son[pos]; } else { return false; } } //走到这一步,表明可能完全匹配,可能部分匹配,如果最后一个字符节点为末端节点,则是完全匹配,否则是部分匹配 return node.isEnd; } // 前序遍历字典树. public void preTraverse(TrieNode node) { if(node!=null) { System.out.print(node.val+"-"); for(TrieNode child:node.son) { preTraverse(child); } } }
public TrieNode getRoot() { return this.root; } public static void main(String[]args) throws IOException { Trie tree=new Trie(); String[] dictionaryData= {"hello","student","computer","sorry","acm","people","experienced","who","reminds","everyday","almost"}; //构建字典 for(String str:dictionaryData) { tree.insert(str); } String filePath="C:\\Users\\Administrator\\Desktop\\sourceFile.txt"; File file=new File(filePath); if(file.isFile() && file.exists()) { InputStreamReader read = new InputStreamReader(new FileInputStream(file)); BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; Map<String,Integer> countMap=new HashMap<String,Integer>(); while((lineTxt = bufferedReader.readLine())!= null) { if(tree.has(lineTxt)) { if(countMap.containsKey(lineTxt)) { countMap.put(lineTxt, countMap.get(lineTxt)+1); } else { countMap.put(lineTxt, 1); } } else { System.out.println(lineTxt+"不在字典中!"); } } for(String s:countMap.keySet()) { System.out.println(s+"出现的次数"+countMap.get(s)); } read.close(); } } }
作者:张晓天a
链接:https://www.jianshu.com/p/d6dcf47c37bc
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦