745-前缀和后缀搜索

标签: 算法 数据结构 leetcode
20人阅读 评论(0) 收藏 举报
分类:

Description

Given many words, words[i] has weight i.

Design a class WordFilter that supports one function, WordFilter.f(String prefix, String suffix). It will return the word with given prefix and suffix with maximum weight. If no word exists, return -1.


Examples:

Input:
WordFilter(["apple"])
WordFilter.f("a", "e") // returns 0
WordFilter.f("b", "") // returns -1

Note:

  1. words has length in range [1, 15000].
  2. For each test case, up to words.length queries WordFilter.f may be made.
  3. words[i] has length in range [1, 10].
  4. prefix, suffix have lengths in range [0, 10].
  5. words[i] and prefix, suffix queries consist of lowercase letters only.

问题描述

给定字符串数组words,words[i]的权重为i。
设计WordsFilter类,支持WordFilter.f(String prefix, String suffix)。
这个函数返回以prefix为前缀,以suffix为后缀的有着最大权重的字符串。
如果没有这样的字符串,那么返回-1。


问题分析

我的做法是通过前缀字典树和后缀字典树找出满足的字符串集合,然后逆序遍历words,判断words[i]是否在字符串集合中(复杂且效率不高)

这个链接记录了另外三种简单的解法,感兴趣的话可以去看看
https://leetcode.com/problems/prefix-and-suffix-search/discuss/110044/Three-ways-to-solve-this-problem-in-Java


解法1(字典树)

class WordFilter {
    //前缀字典树节点
    private class ptNode{
        //拥有该路径为前缀的字符串
        boolean[] prefix;
        ptNode[] children;

        public ptNode(int n){
            prefix = new boolean[n];
            children = new ptNode[26];
        }
    }
    //后缀字典树节点
    private class stNode{
        //拥有该路径为后缀的字符串
        boolean[] suffix;
        stNode[] children;

        public stNode(int n){
            suffix = new boolean[n];
            children = new stNode[26];
        }
    }
    private ptNode proot;
    private stNode sroot;
    private String[] words;
    private int n;
    public WordFilter(String[] words) {
        n = words.length;

        proot = new ptNode(n);
        sroot = new stNode(n);
        this.words = words;
        //遍历words,构造前缀字典树和后缀字典树
        for(int i = 0;i < n;i++){
            addp(proot, words[i], i);
            adds(sroot, words[i], i);
        }
    }

    public int f(String prefix, String suffix) {
        ptNode workNode1 = proot;
        stNode workNode2 = sroot;
        //通过两个循环找出满足指定前缀和后缀的字符串集合
        for(char c : prefix.toCharArray()){
            workNode1 = workNode1.children[c - 'a'];
            if(workNode1 == null)   return -1;
        }

        int i = suffix.length() - 1;
        while(i >= 0){
            workNode2 = workNode2.children[suffix.charAt(i) - 'a'];
            if(workNode2 == null)   return -1;
            i--;
        }
        //逆序遍历words,返回满足条件的字符串
        for(i = n - 1;i >= 0;i--){
            if(workNode1.prefix[i] && workNode2.suffix[i])  return i;
        }

        return -1;
    }
    //构造前缀字典树
    public void addp(ptNode root, String str, int index){
        for(char c : str.toCharArray()){
            //在这里维护满足前缀的字符串数组
            root.prefix[index] = true;
            if(root.children[c - 'a'] == null)  root.children[c - 'a'] = new ptNode(n);
            root = root.children[c - 'a'];
        }
        //还有这里
        root.prefix[index] = true;
    }
    //构造后缀字典树
    public void adds(stNode root, String str, int index){
        int i = str.length() - 1;
        char[] cArr = str.toCharArray();

        while(i >= 0){
            //在这里维护满足后缀的字符串数组
            root.suffix[index] = true;
            if(root.children[cArr[i] - 'a'] == null)  root.children[cArr[i] - 'a'] = new stNode(n);
            root = root.children[cArr[i] - 'a'];
            i--;
        }
        //还有这里
        root.suffix[index] = true;
    }
}

另外两种简单的做法

解法2

class WordFilter {
    //存储满足前缀的权重列表
    HashMap<String, List<Integer>> mapPrefix = new HashMap<>();
    //存储满足后缀的权重列表
    HashMap<String, List<Integer>> mapSuffix = new HashMap<>();

    public WordFilter(String[] words) {
        //循环构建mapPrefix和mapSuffix
        for(int w = 0; w < words.length; w++){
            for(int i = 0; i <= words[w].length(); i++){
                String s = words[w].substring(0, i);
                if(!mapPrefix.containsKey(s)) mapPrefix.put(s, new ArrayList<>());
                mapPrefix.get(s).add(w);
            }
            for(int i = 0; i <= words[w].length(); i++){
                String s = words[w].substring(words[w].length() - i);
                if(!mapSuffix.containsKey(s)) mapSuffix.put(s, new ArrayList<>());
                mapSuffix.get(s).add(w);
            }
        }
    }
    public int f(String prefix, String suffix) {

        if(!mapPrefix.containsKey(prefix) || !mapSuffix.containsKey(suffix)) return -1;
        //得出prefix的权重列表
        List<Integer> p = mapPrefix.get(prefix);
        //得出suffix的权重列表
        List<Integer> s = mapSuffix.get(suffix);
        int i = p.size()-1, j = s.size()-1;
        while(i >= 0 && j >= 0){
            if(p.get(i) < s.get(j)) j--;
            else if(p.get(i) > s.get(j)) i--;
            //若相等,说明找到,直接返回
            else return p.get(i);
        }
        return -1;
    }
}

解法3

class WordFilter {
    HashMap<String, Integer> map = new HashMap<>();

    public WordFilter(String[] words) {
        for(int w = 0; w < words.length; w++){
            for(int i = 0; i <= words[w].length(); i++){
                for(int j = 0; j <= words[w].length(); j++){
                    map.put(words[w].substring(0, i) + "#" + words[w].substring(words[w].length() - j), w);
                }
            }
        }
    }

    public int f(String prefix, String suffix) {
        return (map.containsKey(prefix + "#" + suffix)) ? map.get(prefix + "#" + suffix) : -1;
    }
}
查看评论

leetcode 745. Prefix and Suffix Search 字典树(前缀树)

Given many words, words[i] has weight i.Design a class WordFilter that supports one function, WordFi...
  • JackZhang_123
  • JackZhang_123
  • 2017-12-25 21:31:34
  • 107

在AD中使用多域名DNS Suffix

现在我们使用Windows Server 2003的AD环境,我想实现如下功能: 1、如何更改设置实现DNS Suffix Search List中显示更多的信息(域名)? 2、设置更多的域名在D...
  • fogyisland2000
  • fogyisland2000
  • 2010-11-02 00:06:00
  • 5400

DNS Suffixes List

环境及问题描述:         Server A(SA)用来share文件,Client A(CA)是一台虚拟机,用来做一些测试。Client B(CB)是我的工作机,平时通过CB Remote ...
  • sdwyq1238
  • sdwyq1238
  • 2012-04-13 14:49:59
  • 591

git的基本流程

git的基本流程
  • dong_beijing
  • dong_beijing
  • 2017-12-12 13:39:27
  • 105

746. Prefix and Suffix Search

Given many words, words[i] has weight i. Design a class WordFilter that supports one function, Word...
  • kakitgogogo
  • kakitgogogo
  • 2017-12-31 11:06:54
  • 68

745. Prefix and Suffix Search

Given many words, words[i] has weight i.Design a class WordFilter that supports one function, WordFi...
  • zjucor
  • zjucor
  • 2017-12-10 12:25:05
  • 61

gzip: unknown suffix -- ignored

gzip: unknown suffix -- ignoredgunzip file#识别后缀,必须把后缀改为.gz //解压后的文件名,去掉.gzgunzip -c > urfile.txt htt...
  • wenlifu71022
  • wenlifu71022
  • 2010-01-22 09:55:00
  • 16263

随笔二十八:invalid instruction suffix for push'

主机环境 Fedora 17 X86_64 编写 pushl %ebp 想执行 cc -O1 -c test.s objdump -d test.o 想看看在目标代码中 pushl 指令编码...
  • HMSIWTV
  • HMSIWTV
  • 2012-07-03 08:55:17
  • 8840

mybatis之<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>

1. prefix:在trim标签内sql语句加上前缀。 suffix:在trim标签内sql语句加上后缀。 suffixOverrides:指定去除多余的后缀内容,如:suffixOverri...
  • qq_33054511
  • qq_33054511
  • 2017-04-23 11:07:05
  • 15751

java web配置prefix suffix的是什么意思

prefix和suffix的含义
  • gd911202
  • gd911202
  • 2017-03-17 00:21:00
  • 795
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 6812
    排名: 4382
    博客专栏
    文章存档
    最新评论