LintCode 单词搜索Ⅱ 字典树

今天做了道有意思的题目,题目要解出来不难,但看到他的提示

发现这道题我一开始并没有用到字典树

然后就使用字典树+DFS写了一遍,也算是巩固下字典树的相关知识

题目:原题地址

给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。

样例

给出矩阵:

doafagaidcan

和字典:

{"dog", "dad", "dgdg", "can", "again"}

返回 {"dog", "dad", "can", "again"}

挑战

使用单词查找树来实现你的算法

解题思路:

先对给的字典建立一颗字典树,然后使用DFS在给的矩阵内搜索字典树,相关注释现在了代码里。

下面贴代码:

package ww;

import java.util.ArrayList;
import java.util.Arrays;

import org.junit.Test;

public class TestDC {

    @Test
    //测试用例
    //输出:[dog, dad, again, can]
    public void test() {
        char[][] board = { { ‘d‘, ‘o‘, ‘a‘, ‘f‘ }, { ‘a‘, ‘g‘, ‘a‘, ‘i‘ }, { ‘d‘, ‘c‘, ‘a‘, ‘n‘ } };
        ArrayList<String> list = new ArrayList<String>();
        String[] tem = { "dog", "dad", "dgdg", "can", "again" };
        for (String tt : tem) {
            list.add(tt);
        }
        ArrayList<String> wordSearchII = wordSearchII(board, list);
        System.out.println(wordSearchII);
    }

    int MAX_N = 1000000;//字典树最大深度
    int MAX_C = 26;//表示26个小写字母
    int tot = 0;//用于记录位置
    String[] ch;//用来标记结尾的字母所对应的单词
    int[][] cnt;//用来表示字典树

    //初始化字典树
    public void init() {
        ch = new String[MAX_N];
        cnt = new int[MAX_N][];

        Arrays.fill(ch, null);
        Arrays.fill(cnt, null);
    }

    //构建字典树
    public void insert(String str) {
        int p = 0;
        for (char ch : str.toCharArray()) {
            if (cnt[p] == null) {
                cnt[p] = new int[MAX_C];
                Arrays.fill(cnt[p], -1);
            }

            /**
             * 表示该单词下一个字母应对应的位置
             */
            if (cnt[p][ch - ‘a‘] == -1) {
                cnt[p][ch - ‘a‘] = ++tot;
            }
            p = cnt[p][ch - ‘a‘];
        }
        //表示这个单词插入玩成,在字典树对应的最后一个字母上,标记这个单词,以便查找
        if (ch[p] == null) {
            ch[p] = str;
        }
    }

//支持1.8的话,使用下面的Stream去重。不支持的话使用HashSet去重
//原理相同
//      public void dfsFind(char[][] board, boolean[][] visited, int row, int col, int p, HashSet<String> list) {
//        if (ch[p] != null) {
//            list.add(ch[p]);
//        }
//        if (row >= 0 && row < board.length && col >= 0 && col < board[0].length && visited[row][col] == false
//                && (cnt[p] != null) && (p = cnt[p][board[row][col] - ‘a‘]) != -1) {
//            visited[row][col] = true;
//
//            dfsFind(board, visited, row - 1, col, p, list);
//            dfsFind(board, visited, row, col + 1, p, list);
//            dfsFind(board, visited, row + 1, col, p, list);
//            dfsFind(board, visited, row, col - 1, p, list);
//            visited[row][col] = false;
//
//        }
//
//    }
//
//    public ArrayList<String> wordSearchII(char[][] board, ArrayList<String> words) {
//        init();
//        for (String str : words) {
//            insert(str);
//        }
//        boolean[][] visited = new boolean[board.length][board[0].length];
//        HashSet<String> list = new HashSet<String>();
//        for (int i = 0; i < board.length; i++) {
//            for (int j = 0; j < board[0].length; j++) {
//                dfsFind(board, visited, i, j, 0, list);
//            }
//        }
//        ArrayList<String> rl = new ArrayList<String>();
//        Iterator<String> iterator = list.iterator();
//        while (iterator.hasNext()) {
//            rl.add(iterator.next());
//        }
//        return rl;
//    }

    //dfs搜索寻找单词
    public void dfsFind(char[][] board, boolean[][] visited, int row, int col, int p, ArrayList<String> list) {
        //找到了,加入list
        if (ch[p] != null) {
            list.add(ch[p]);
        }
        //依次向4个方向搜索
        if (row >= 0 && row < board.length && col >= 0 && col < board[0].length && visited[row][col] == false
                && (cnt[p] != null) && (p = cnt[p][board[row][col] - ‘a‘]) != -1) {
            visited[row][col] = true;

            dfsFind(board, visited, row - 1, col, p, list);
            dfsFind(board, visited, row, col + 1, p, list);
            dfsFind(board, visited, row + 1, col, p, list);
            dfsFind(board, visited, row, col - 1, p, list);
            visited[row][col] = false;

        }

    }

    public ArrayList<String> wordSearchII(char[][] board, ArrayList<String> words) {
        init();//字典树的初始化
        //构建字典树
        for (String str : words) {
            insert(str);
        }
        //用于标记以走过的路程
        boolean[][] visited = new boolean[board.length][board[0].length];
        ArrayList<String> list = new ArrayList<String>();
        //搜索
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                dfsFind(board, visited, i, j, 0, list);
            }
        }
        //去重
        ArrayList<String> rl = new ArrayList<String>();
        list.stream().distinct().forEach(rl::add);
        return rl;
    }
}
时间: 2024-08-26 07:39:41

LintCode 单词搜索Ⅱ 字典树的相关文章

hdu1247Hat’s Words (组合单词,字典树+DFS)

Problem Description A hat's word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary. You are to find all the hat's words in a dictionary. Input Standard input consists of a number of lowercase words, on

hdu2072 单词数 字典树

字典树裸题 1 #include<stdio.h> 2 #include<string.h> 3 int next[5000][26]; 4 bool is_e[5000]; 5 int cnt; 6 int ans; 7 8 void Insert(char *word,int s1){ 9 int root=0; 10 for(int i=0;i<s1;i++){ 11 if(next[root][word[i]-'a']<0){ 12 next[root][wor

hdu 1247 Hat’s Words 字典树,还是比较有意思的题目

Hat's Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8843    Accepted Submission(s): 3171 Problem Description A hat's word is a word in the dictionary that is the concatenation of exactl

Word Puzzles(字典树)

Description Word puzzles are usually simple and very entertaining for all ages. They are so entertaining that Pizza-Hut company started using table covers with word puzzles printed on them, possibly with the intent to minimise their client's percepti

hdu 1247:Hat’s Words(字典树,经典题)

Hat's Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7282    Accepted Submission(s): 2639 Problem Description A hat's word is a word in the dictionary that is the concatenation of exactly

ZOJ 3674 Search in the Wiki(字典树 + map + vector)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4917 题意:每个单词都一些tips单词.先输入n个单词和他们的tips.然后m组查询,每次查询一些单词,按字典序输出这些单词的公有tips.(每个单词都都只包含小写大写字母) 思路:对第i个单词,用vector数组g,g[i]来存这个单词的所有tips.对于所有单词建立字典树,在单词的结尾结点存好该单词的tips在g数组中存的一维下标i.最后用map来计数每组询问中

hdu1247 Hat’s Words 字典树

Problem Description A hat's word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary. You are to find all the hat's words in a dictionary. Input Standard input consists of a number of lowercase words, on

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类

LA3942 Remember the Word(字典树+记忆化搜索)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22109 题意:给出一个由S个不同单词组成的字典和一个长字符串.把这个字符串分解成若干个单词的连接(单词可以重复使用),由多少种方法?比如,有4个单词a,b,cd,ab,则abcd有两种分解方法:a+b+cd和ab+cd 分析:首先将输入的字典建成字典树.然后记忆化搜索~ 代码: #include <iostream> #include <cstring>