题目地址:
https://leetcode.com/problems/index-pairs-of-a-string/
给定一个字符串 s s s,再给定一个字符串数组,如果数组中一个字符串是 s s s的子串,那么就记下该子串在 s s s中的起始和结尾的下标(包括起始字符和结尾字符的下标)。返回所有这样的下标。
思路是用Trie。先将数组中所有字符串存入一个Trie,然后从 s s s的每一个位置 i i i开始,在Trie中搜索是否存在 s [ i : ] s[i:] s[i:]的前缀,如果存在,则返回所有前缀的结尾下标。
import java.util.ArrayList;
import java.util.List;
public class Solution {
class Trie {
class Node {
boolean isWord;
Node[] next;
Node() {
next = new Node[26];
}
}
private Node root;
Trie(String[] words) {
root = new Node();
for (String word : words) {
insert(word);
}
}
private void insert(String word) {
Node cur = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (cur.next[c - 'a'] == null) {
cur.next[c - 'a'] = new Node();
}
cur = cur.next[c - 'a'];
}
cur.isWord = true;
}
// 在Trie里查找所有word[start:]的前缀,并把前缀的结尾字符的下标返回
public List<Integer> hasPrefix(String word, int start) {
List<Integer> end = new ArrayList<>();
Node cur = root;
for (int i = start; i < word.length(); i++) {
char c = word.charAt(i);
// 走到null的时候说明更长的前缀不可能再有了,退出循环
if (cur.next[c - 'a'] == null) {
break;
}
cur = cur.next[c - 'a'];
// 找到一个前缀,就将其结尾下标加入list
if (cur.isWord) {
end.add(i);
}
}
return end;
}
}
public int[][] indexPairs(String text, String[] words) {
List<int[]> list = new ArrayList<>();
Trie trie = new Trie(words);
// 查找text[i:]在trie里存在的所有前缀,并把区间端点加入list
for (int i = 0; i < text.length(); i++) {
for (int end : trie.hasPrefix(text, i)) {
list.add(new int[]{i, end});
}
}
// 转为数组返回
int[][] res = new int[list.size()][];
for (int i = 0; i < res.length; i++) {
res[i] = list.get(i);
}
return res;
}
}
时间复杂度 O ( ( n + m ) l ) O((n+m)l) O((n+m)l), n n n为text长度, m m m为words字符串个数, l l l为words里最长字符串的长度。空间复杂度 O ( ( n + m ) l ) O((n+m)l) O((n+m)l)。