Number of Matching Subsequences LT729

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].

Idea1. Bruteforce, for each word, scan the string S to see if the word is a subseq.

Time complexity: O(S.length()* O(words.length*word.length()), like O(n*m)

Space complexity: O(1)

 1 class Solution {
 2     boolean isSubseq(String S, String word){  
 3         for(int i = 0, j = 0; j < S.length(); ++j) {
 4             if(S.charAt(j) == word.charAt(i)) {
 5                 ++i;
 6                 if(i == word.length()) {
 7                     return true;
 8                 }
 9             }
10         }
11         
12         return false;
13     }
14     public int numMatchingSubseq(String S, String[] words) {
15         int count = 0;
16         for(String word: words) {
17             if(isSubseq(S, word)) {
18                 ++count;
19             }
20         }
21         return count;
22     }
23 }

Idea 2. Store the prefix char for each words, scan string S only once, it's linear

Time complexity: O(n + m)

Space complexity: O(1)

use map to store pair(char, {{words index, next char index} }) for scanning next character, scan each word only once to build the map

 1 class Solution {
 2     public int numMatchingSubseq(String S, String[] words) {
 3         Map<Character, List<List<Integer>>> wordsPosition = new HashMap<>();
 4        
 5         for(int i = 0; i < words.length; ++i) {
 6             wordsPosition.computeIfAbsent(words[i].charAt(0), (key -> new ArrayList<>())).add(Arrays.asList(i, 1));
 7         }
 8         
 9         int result = 0;
10         for(int i = 0; i < S.length(); ++i) {
11             char c = S.charAt(i);
12            
13             List<List<Integer>> copy = new ArrayList<>(wordsPosition.getOrDefault(c, Collections.emptyList()));
14             wordsPosition.remove(c);
15             
16             for(List<Integer> position: copy) {
17                 int wordIndex = position.get(0);
18                 int charIndex = position.get(1);
19                 if(charIndex == words[wordIndex].length()) {
20                     ++result;
21                 }
22                 else {
23                     wordsPosition.computeIfAbsent(words[wordIndex].charAt(charIndex), (key -> new ArrayList<>())).add(Arrays.asList(wordIndex, charIndex+1));
24                 }
25             }
26         }
27         
28         return result;
29     }
30 }

use String CharacterIterator, save the need to store wordIndex, we can locate the next char with CharacterIterator only.

 1 import java.text.StringCharacterIterator;
 2 import java.text.CharacterIterator;
 3 
 4 class Solution {
 5     public int numMatchingSubseq(String S, String[] words) {
 6         int len = 128;
 7         List<List<StringCharacterIterator>> wordsPosition = new ArrayList<>();
 8         for(int i = 0; i < len; ++i) {
 9             wordsPosition.add(new ArrayList<>());
10         }
11        
12       
13         for(int i = 0; i < words.length; ++i) {
14             wordsPosition.get(words[i].charAt(0) - 'a').add(new StringCharacterIterator(words[i]));
15         }
16         
17         int result = 0;
18         for(int i = 0; i < S.length(); ++i) {
19             int c = S.charAt(i) - 'a';
20            
21             List<StringCharacterIterator> copy = new ArrayList<>(wordsPosition.get(c));
22             
23             wordsPosition.get(c).clear();
24 
25             for(StringCharacterIterator iter: copy) {
26                 char next = iter.next();
27                 if(next == CharacterIterator.DONE) {
28                     ++result;
29                 }
30                 else {
31                     wordsPosition.get(next - 'a').add(iter);
32                 }
33             }
34         }
35         
36         return result;
37     }
38 }

猜你喜欢

转载自www.cnblogs.com/taste-it-own-it-love-it/p/10824080.html