Number of Matching Subsequences

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 in words that are a subsequence of S: "a", "acd", "ace".

Note:

  • All words in words and S 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;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值