Given string S
and a dictionary of words words
, find the number of words[i]
that is a subsequence of S
.
Example : Input: S = "abcde" words = ["a", "bb", "acd", "ace"] Output: 3 Explanation: There are three words inwords
that are a subsequence ofS
: "a", "acd", "ace".
Note:
- All words in
words
andS
will only consists of lowercase letters. - The length of
S
will be in the range of[1, 50000]
. - The length of
words
will be in the range of[1, 5000]
. - The length of
words[i]
will be in the range of[1, 50]
.
思路1:
第一步:用hashmap统计,以字母开头的单词list
第二步:扫描S,遇见字母,就把相应的list里面的单词,如果当前单词长度为1,则是子序列,数量+1。若长度不为1,去掉头部,然后按照剩下的string,按照头部分配到其他的list中去。
T: len(S) S * (number of words) M * (average length of word) L
class Solution {
public int numMatchingSubseq(String S, String[] words) {
HashMap<Character, Queue<String>> map = new HashMap<>();
for(char c = 'a'; c <= 'z'; c++) {
map.putIfAbsent(c, new LinkedList<String>());
}
for(String word: words) {
map.get(word.charAt(0)).add(word);
}
int count = 0;
for(char c : S.toCharArray()){
Queue<String> queue = map.get(c);
int size = queue.size();
for(int j = 0; j < size; j++) {
String cur = queue.poll();
if(cur.length() == 1) {
count++;
} else {
String remain = cur.substring(1);
map.get(remain.charAt(0)).add(remain);
}
}
}
return count;
}
}
思路2:用binary search,首先对S进行预处理,把所有 char的index存一个list到hashmap里面;然后对每个单词,进行扫描,对于c,找到S的index,然后对于后面的char,要binary search找对应list的比当前S index大的index,如果能够找到,那就表明当前word是S的subsequence,如果找不到,那么就表明当前word不是subsequence;O(S + M * L * log(S));
class Solution {
public int numMatchingSubseq(String S, String[] words) {
List<Integer>[] indexList = new List[26];
for(char c = 'a'; c <= 'z'; c++) {
indexList[c - 'a'] = new ArrayList<>();
}
for(int i = 0; i < S.length(); i++) {
char c = S.charAt(i);
indexList[c - 'a'].add(i);
}
int count = 0;
for(String word: words) {
int cur = 0;
for(int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
cur = binarySearch(indexList[c - 'a'], cur);
if(cur == -1) {
break;
}
cur++; // 记住这里要++,找下一个index;
}
if(cur != -1) {
count++;
}
}
return count;
}
// 找到list中第一个大于等于index的值;
private int binarySearch(List<Integer> list, int index) {
if(list.size() == 0) { // 这里要判断list为空;
return -1;
}
int start = 0; int end = list.size() - 1;
while(start + 1 < end) {
int mid = start + (end - start) / 2;
if(index >= list.get(mid)) {
start = mid;
} else {
end = mid;
}
}
if(list.get(start) >= index) {
return list.get(start);
}
if(list.get(end) >= index) {
return list.get(end);
}
return -1;
}
}