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.

这道题给了我们一些单词,让我们通过输入单词的前缀和后缀来查找单词的位置。单词的位置就是其权重值,如果给定的前后缀能对应到不只一个单词,那么返回最大的权重。首先,一个单词如果长度为n的话,那么其就有n个前缀,比如对于单词apple,其前缀即为"a", "ap", "app", "appl", "apple",同理,后缀也有n个。那么其组成的情况就有n2个,所以最简单的方法就是把这n2个前后缀组成一个字符串,和当前权重建立映射。如果后面的单词有相同的前后缀,直接用后面的大权重来覆盖之前的权重即可。为了将前后缀encode成一个字符串,我们可以在中间加上一个非字母字符,比如'#',然后在查找的时候,我们先拼出“前缀#后缀”字符串,直接去哈希map中找即可,这种解法的WordFilter函数时间复杂度为O(NL^2),其中N是单词个数,L是单词长度。f函数时间复杂度为O(1),空间复杂度为O(NL^2),适合需要大量查找的情况下使用,参见代码如下:

class WordFilter {
public:
WordFilter(vector<string> words) {
for (int k = ; k < words.size(); ++k) {
for (int i = ; i <= words[k].size(); ++i) {
for (int j = ; j <= words[k].size(); ++j) {
m[words[k].substr(, i) + "#" + words[k].substr(words[k].size() - j)] = k;
}
}
}
} int f(string prefix, string suffix) {
return (m.count(prefix + "#" + suffix)) ? m[prefix + "#" + suffix] : -;
} private:
unordered_map<string, int> m;
};

如果我们希望节省一些空间的话,可以使用下面的方法。使用两个哈希map,一个建立所有前缀和权重数组之间的映射,另一个建立所有后缀和权重数组之间的映射。在WordFilter函数中,我们遍历每个单词,然后先遍历其所有前缀,将遍历到的前缀的映射数组中加入当前权重,同理再遍历其所有后缀,将遍历到的后缀的映射数组中加入当前权重。在搜索函数f中,首先判断,如果前缀或后缀不存在的话,直接返回-1。否则我们分别把前缀和后缀的权重数组取出来,然后用两个指针i和j,分别指向数组的最后一个位置。当i和j不小于0时进行循环,如果两者的权重相等,直接返回,如果前缀的权重数组值大,则j自减1,反之i自减1,这种解法的WordFilter函数时间复杂度为O(NL),其中N是单词个数,L是单词长度。f函数时间复杂度为O(N),空间复杂度为O(NL),参见代码如下:

解法二:

class WordFilter {
public:
WordFilter(vector<string> words) {
for (int k = ; k < words.size(); ++k) {
for (int i = ; i <= words[k].size(); ++i) {
mp[words[k].substr(, i)].push_back(k);
}
for (int i = ; i <= words[k].size(); ++i) {
ms[words[k].substr(words[k].size() - i)].push_back(k);
}
}
} int f(string prefix, string suffix) {
if (!mp.count(prefix) || !ms.count(suffix)) return -;
vector<int> pre = mp[prefix], suf = ms[suffix];
int i = pre.size() - , j = suf.size() - ;
while (i >= && j >= ) {
if (pre[i] < suf[j]) --j;
else if (pre[i] > suf[j]) --i;
else return pre[i];
}
return -;
} private:
unordered_map<string, vector<int>> mp, ms;
};

moto72大神的帖子中还有第三种解法,但是C++中没有startsWith()和endsWith()函数,以至于无法写出C++版本的,还是Java比较叼啊。

类似题目:

Add and Search Word - Data structure design

参考资料:

https://discuss.leetcode.com/topic/113547/three-ways-to-solve-this-problem-in-java

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Prefix and Suffix Search 前后缀搜索的更多相关文章

  1. [Swift]LeetCode745. 前缀和后缀搜索 | Prefix and Suffix Search

    Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...

  2. 【leetcode】745. Prefix and Suffix Search

    题目如下: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, ...

  3. 745. Prefix and Suffix Search 查找最大index的单词

    [抄题]: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, ...

  4. Prefix and Suffix Search

    Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...

  5. Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)

    Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...

  6. Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)

    745. 前缀和后缀搜索 给定多个 words,words[i] 的权重为 i . 设计一个类 WordFilter 实现函数WordFilter.f(String prefix, String su ...

  7. Objective-C 【NSString-字符串比较&前后缀检查及搜索】

    ———————————————————————————————————————————NSString 字符串比较 #import <Foundation/Foundation.h> vo ...

  8. Leetcode之回溯法专题-79. 单词搜索(Word Search)

    Leetcode之回溯法专题-79. 单词搜索(Word Search) 给定一个二维网格和一个单词,找出该单词是否存在于网格中. 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元 ...

  9. poj 2752 Seek the Name, Seek the Fame【KMP算法分析记录】【求前后缀相同的子串的长度】

    Seek the Name, Seek the Fame Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14106   Ac ...

随机推荐

  1. New UWP Community Toolkit - XAML Brushes

    概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...

  2. ConcurrentHashMap 源码分析

    ConcurrentHashMap 源码分析 1. 前言    终于到这个类了,其实在前面很过很多次这个类,因为这个类代码量比较大,并且涉及到并发的问题,还有一点就是这个代码有些真的晦涩,不好懂.前前 ...

  3. Python中协程的实现

    通过关键字yield,可以从生成器中产生值,并返回.我们可以将生成器作为一个生产者来使用. 在协程中,通过使用关键字yield,还可以让具有yield的程序接收值.此时函数作为消费者,消费我们传入(s ...

  4. Entity Framework——并发策略

    使用EF框架遇到并发时,一般采取乐观并发控制. 1支持并发检验 为支持并发检验,需要对实体进行额外的设置.默认情况下是不支持并发检验的.有以下两种方式: 方式名称 说明 时间戳注解/行版本 使用Tim ...

  5. 面试常考---html篇

    1.html5新特性,语义化 HTML5为我们提供了一系列的语义标签. 1.<section></section> 定义文档中的主体部分的节.段. 2.<article& ...

  6. apache学习教程

    5.apache教程 httpd.conf文件分析 ServerRoot "E:/phpwebenv/PHPTutorial/Apache" #apache软件安装的位置 List ...

  7. Java基础学习笔记十四 常用API之基本类型包装类

    基本类型包装类 Java中有8种基本的数据类型,可是这些数据是基本数据,想对其进行复杂操作,变的很难.怎么办呢?在实际程序使用中,程序界面上用户输入的数据都是以字符串类型进行存储的.而程序开发中,我们 ...

  8. 记录python接口自动化测试--requests使用和基本方法封装(第一目)

    之前学习了使用jmeter+ant做接口测试,并实现了接口的批量维护管理(大概500多条用例),对"接口"以及"接口测试"有了一个基础了解,最近找了一些用pyt ...

  9. 事后诸葛亮分析——Beta版本

    事后诸葛亮分析 请两个小组在Deadline之前,召开事后诸葛亮会议,发布一篇事后分析报告. 软件工程课的目的,主要是让大家通过做项目,学到软件工程的知识,而不是低水平重复. 软件=程序+软件工程,软 ...

  10. 201621123050 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...