hihoCoder:Trie图

来源:互联网 发布:sql join where 区别 编辑:程序博客网 时间:2024/05/10 08:11


详细的文章题目链接如下 :http://hihocoder.com/problemset/problem/1036

这周的题目没有做,现在补上,但是还是要学习一下思路。

题目要求:给出一篇长篇的文章,和一本字典(里面包含了很多英文单词),问那些文章中

那些词语在词典中出现,朴素的做法就是,直接枚举话,假设词语数量为N,每个词语长度为L,

文章的长度为M,时间上要O(N*L*M),

(1)使用Trie树,把所有字典建立起一颗trie树,那么对于文章中的匹配就是从第一个字符串开始,

在trie树中进行路径选择,当找到一个标记节点的时候表示匹配到一个词语;当文章的当前字符

串找不到下一个路径时候,表示第一个字符串开头的不是字典中的词,继续从第二个字符串开始

匹配,依次类推;

(2)显然,在我们匹配的过程中,我们既然已经从str的当前起点i开始匹配了l个长度,那么在枚举str的下一个起点i+1的时候,就意味着最开始的l-1个字符都已经在之前的计算中匹配过了,如果我们能够利用好这个信息的话,就能够大大的减少时间复杂度。”“换句话说,如果我们从str的当前起点开始,匹配了l个长度走到了A结点,如果我们把A结点对应的字符串(即从tree的0号走到A结点的路径)去掉第一个字符,形成一个新的字符串,那么这个字符串肯定是和从str的下一个起点开始,长度为l-1的子串是一样的,而如果我们能够预先找到这个字符串在tree中对应的结点B',我们就不用像之前所说的那样从0号节点走到A结点然后回到0号结点再走到B结点,而是可以直接从0号结点走到A结点然后直接跳转到B’结点然后再根据从str[i+l..k1]这一段走到B结点!

所以我们的问题规约成了:如何对于一棵给定的Trie树,找到其中每一个结点对应的后缀结点——所谓的后缀

结点就是这个结点在Trie中对应路径去掉第一个字符之后在Trie中对应的结点。

(3)对于一个trie树,可以知道,

根节点(也就是空串),去掉第一个字符之后也是空串;

与根结点相连的,也就是一级结点,去掉第一个字符,也就是他自己本身,所以一级结点的后缀结点是根结点

接着,我们继续看二级结点,显然二级结点的父节点是与他相连的一级结点,他们通过字符串‘x',假设;

那么二级结点的后缀结点就是((一级结点的后缀结点)通过字符串’x‘相连的子节点了)

依次递推,就可以求出所有结点的后缀结点
下面是我的AC代码,脑残了,有些细节写快,纠结两天,睡觉

import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Scanner;/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. *//** * * @author yuan */public class Main {        public static void main(String[] args) throws FileNotFoundException {        Scanner cin ;        cin = new Scanner(System.in);   //     FileInputStream ins = new FileInputStream(new File("in"));  //      cin = new Scanner(ins);        int n;        n = cin.nextInt();//        System.out.println(n);        String context = null;        TrieMap trieMap = new TrieMap();        for(int i = 0; i < n; ++i){            trieMap.insert(cin.next());        }        trieMap.adjustEndNode();//        System.out.println(trieMap.foreach());        context = cin.next();        System.out.println(trieMap.find(context) ? "YES" : "NO");    }    public static class TrieMap {        TrieNode head;        public static final int SIZE = 30;        public static final int WORDLENGTH = 1001;        public TrieMap() {            head = new TrieNode();            head.nextNode = head;        }                public List<String> foreach(){            ArrayList<String> list = new ArrayList<>();            char[] chs = new char[WORDLENGTH];            backTrace(list, this.head, chs, 0);            return list;        }                private void backTrace(List<String> list, TrieNode curNode, char[] chs, int cur){            Collection<TrieNode> children = curNode.children.values();            for(TrieNode node : children){                chs[cur] = node.ch;                backTrace(list, node, chs, cur + 1);                if(node.isEndNode){                    list.add(new String(chs, 0, cur + 1));                }            }        }        public void insert(String str) {            char chs[] = str.toCharArray();            TrieNode curNode = this.head;            for (int i = 0; i < chs.length; ++i) {                TrieNode node = curNode.children.get(chs[i]);                if (node == null) {                    node = new TrieNode(chs[i]);                    curNode.children.put(chs[i], node);                }                curNode = node;            }            curNode.isEndNode = true;        }        public void adjustEndNode() {            LinkedList<TrieNode> queue = new LinkedList<>();            this.head.nextNode = this.head;            Collection<TrieNode> children = this.head.children.values();            for(TrieNode node : children){                node.nextNode = this.head;                queue.add(node);            }//            System.out.println(queue);            TrieNode curNode = null;            while(!queue.isEmpty()){                   curNode = queue.removeFirst();                children = curNode.children.values();                for(TrieNode node : children){                    node.nextNode = curNode.nextNode.children.get(node.ch);                    if(node.nextNode == null){                        node.nextNode = this.head;                    }                    queue.add(node);                }            }        }        public boolean find(String str) {            boolean flag = false;            char[] chs = str.toCharArray();            TrieNode curNode = this.head;            TrieNode node = null;            for (int i = 0; i < chs.length;++i) {                node = curNode.children.get(chs[i]);                if (node == null) {                    node = curNode.nextNode;                } else if (node.isEndNode) {                    flag = true;                    break;                }                curNode = node;            }            return flag;        }    }    public static class TrieNode {        boolean isEndNode = false;        char ch = ' ';        HashMap<Character, TrieNode> children;        TrieNode nextNode = null;        public TrieNode(Character ch) {            this.isEndNode = false;            this.ch = ch;            this.children = new HashMap<>(TrieMap.SIZE);            this.nextNode = null;        }        public TrieNode() {            this(' ');        }                @Override        public String toString(){            return super.toString();        }    }}


 

0 0
原创粉丝点击