Open azl397985856 opened 1 week ago
class Solution {
public int[][] multiSearch(String big, String[] smalls) {
// 思路:将smalls中的字符串构建出一个前缀树 写一个search(word)方法 查询树中是否有word的前缀 并将其返回
// 这个和之前的实现前缀树的不同点在于
// 之前是startWithPrefix判断树中是否有字符串的前缀为prefix;这次是要返回树中word的所有前缀,并且树节点的val存储树中字符串值
Trie root = new Trie();
for (String word : smalls) {
root.insert(word);
}
// resMap存储每个smalls中word在target中的开始索引值们
Map<String, List<Integer>> resMap = new HashMap();
int n = big.length();
for (int i = 0; i < n; i++) {
String target = big.substring(i);
List<String> prefixs = root.searchPrefixListOfTarget(target);
for (String word : prefixs) {
// 为啥getOrDefault没用
// resMap.getOrDefault(word, new ArrayList()).add(i);
if(!resMap.containsKey(word)){
resMap.put(word, new ArrayList<>());
}
resMap.get(word).add(i);
}
}
// 把resMap转成对应的数组
// 不能直接初始化res长度为new int[smalls.length][n] 不然就会被赋初始值0
int[][] res = new int[smalls.length][];
for (int i = 0; i < smalls.length; i++) {
String word = smalls[i];
List<Integer> indexs = resMap.get(word);
if (indexs == null || indexs.size() == 0) {
res[i] = new int[0];
continue;
}
int j = 0;
res[i] = new int[indexs.size()];
for (int index : indexs) {
res[i][j++] = index;
}
}
return res;
}
class Trie {
String val;
Trie[] child;
public Trie() {
child = new Trie[26];
}
void insert(String word) {
Trie cur = this;
for (char c : word.toCharArray()) {
if (cur.child[c - 'a'] == null) {
cur.child[c - 'a'] = new Trie();
}
cur = cur.child[c - 'a'];
}
// 节点中存储word字符串
cur.val = word;
}
// 获取 在target中是前缀的当前树中的字符串
List<String> searchPrefixListOfTarget(String target) {
Trie cur = this;
List<String> res = new ArrayList();
for (char c : target.toCharArray()) {
// 如果发现前缀不匹配了 直接break
if (cur.child[c - 'a'] == null) {
break;
}
cur = cur.child[c - 'a'];
if (cur.val != null && cur.val != "") {
res.add(cur.val);
}
}
return res;
}
}
}
smalls构建前缀树,big子集遍历
import collections
class Trie:
def __init__(self, words):
self.d = {}
# t = self.d 不能写在循环外面,一次到底了
for word in words:
t = self.d # 回到头部,回到字典嵌套第一层而不是尾层
for w in word:
if w not in t:
t[w] = {}
t = t[w]
t['end'] = word
# 不止一个根的前缀树
def search(self, s):
t = self.d
res = []
for w in s:
if w not in t:
break
t = t[w]
if 'end' in t:
res.append(t['end'])
return res
class Solution:
def multiSearch(self, big: str, smalls: List[str]) -> List[List[int]]:
node = Trie(smalls)
dic = collections.defaultdict(list)
for i in range(len(big)):
match_words = node.search(big[i:])
for word in match_words:
dic[word].append(i)
ans = []
for word in smalls:
ans.append(dic[word])
return ans
时间复杂度: $O(n*m)$ n表示big的长度
空间复杂度: $O(m*k)$ m表示smalls的长度,k表示smalls中最长字符串的长度,最坏的情况时都匹配上
class Trie:
def __init__(self, words):
self.d = {}
for word in words:
t = self.d
for w in word:
if w not in t:
t[w] = {}
t = t[w]
t['end'] = word
def search(self, s):
t = self.d
res = []
for w in s:
if w not in t:
break
t = t[w]
if 'end' in t:
res.append(t['end'])
return res
class Solution:
def multiSearch(self, big: str, smalls: List[str]) -> List[List[int]]:
trie = Trie(smalls)
hit = collections.defaultdict(list)
for i in range(len(big)):
matchs = trie.search(big[i:])
for word in matchs:
hit[word].append(i)
res = []
for word in smalls:
res.append(hit[word])
return res
class Trie:
def __init__(self, words):
self.d = {}
for word in words:
t = self.d
for w in word:
if w not in t:
t[w] = {}
t = t[w]
t['end'] = word
def search(self, s):
t = self.d
res = []
for w in s:
if w not in t:
break
t = t[w]
if 'end' in t:
res.append(t['end'])
return res
class Solution:
def multiSearch(self, big: str, smalls: List[str]) -> List[List[int]]:
trie = Trie(smalls)
hit = collections.defaultdict(list)
for i in range(len(big)):
matchs = trie.search(big[i:])
for word in matchs:
hit[word].append(i)
res = []
for word in smalls:
res.append(hit[word])
return res
class Solution {
public:
struct Trie{
int smallIndex;
Trie next[26];
Trie(){
smallIndex=-1;
memset(next,0,sizeof(next));
}
};
vector<vector
void search(string subBig,int index){
Trie* node=root;
for(auto ch:subBig){
if(node->next[ch-'a']==NULL) return;
node=node->next[ch-'a'];
if(node->smallIndex!=-1){
res[node->smallIndex].push_back(index);
}
}
}
vector<vector<int>> multiSearch(string big, vector<string>& smalls) {
res.resize(smalls.size());
for(int i=0;i<smalls.size();i++){
insert(smalls[i],i);
}
for(int i=0;i<big.size();i++){
string subBig=big.substr(i);
search(subBig,i);
}
return res;
}
};
面试题 17.17 多次搜索
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/multi-search-lcci
前置知识
题目描述
示例:
输入: big = "mississippi" smalls = ["is","ppi","hi","sis","i","ssippi"] 输出: [[1,4],[8],[],[3],[1,4,7,10],[5]] 提示:
0 <= len(big) <= 1000 0 <= len(smalls[i]) <= 1000 smalls 的总字符数不会超过 100000。 你可以认为 smalls 中没有重复字符串。 所有出现的字符均为英文小写字母。