Trie
Array
Hash Table
String
Binary Search
Dynamic Programming
Sorting
Description
Given a string s
and an array of strings words
, return the number of words[i]
that is a subsequence of s
.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
For example, "ace"
is a subsequence of "abcde"
.
Example 1:
Input: s = "abcde", words = ["a","bb","acd","ace"]
Output: 3
Explanation: There are three strings in words that are a subsequence of s: "a", "acd", "ace".
Example 2:
Input: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
Output: 2
Constraints:
1 <= s.length <= 5 * 104
1 <= words.length <= 5000
1 <= words[i].length <= 50
s
and words[i]
consist of only lowercase English letters.
Solutions
Solution 1
Python3 Java C++ Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14 class Solution :
def numMatchingSubseq ( self , s : str , words : List [ str ]) -> int :
d = defaultdict ( deque )
for w in words :
d [ w [ 0 ]] . append ( w )
ans = 0
for c in s :
for _ in range ( len ( d [ c ])):
t = d [ c ] . popleft ()
if len ( t ) == 1 :
ans += 1
else :
d [ t [ 1 ]] . append ( t [ 1 :])
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 class Solution {
public int numMatchingSubseq ( String s , String [] words ) {
Deque < String >[] d = new Deque [ 26 ] ;
Arrays . setAll ( d , k -> new ArrayDeque <> ());
for ( String w : words ) {
d [ w . charAt ( 0 ) - 'a' ] . add ( w );
}
int ans = 0 ;
for ( char c : s . toCharArray ()) {
var q = d [ c - 'a' ] ;
for ( int k = q . size (); k > 0 ; -- k ) {
String t = q . pollFirst ();
if ( t . length () == 1 ) {
++ ans ;
} else {
d [ t . charAt ( 1 ) - 'a' ] . offer ( t . substring ( 1 ));
}
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 class Solution {
public :
int numMatchingSubseq ( string s , vector < string >& words ) {
vector < queue < string >> d ( 26 );
for ( auto & w : words ) d [ w [ 0 ] - 'a' ]. emplace ( w );
int ans = 0 ;
for ( char & c : s ) {
auto & q = d [ c - 'a' ];
for ( int k = q . size (); k ; -- k ) {
auto t = q . front ();
q . pop ();
if ( t . size () == 1 )
++ ans ;
else
d [ t [ 1 ] - 'a' ]. emplace ( t . substr ( 1 ));
}
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 func numMatchingSubseq ( s string , words [] string ) ( ans int ) {
d := [ 26 ][] string {}
for _ , w := range words {
d [ w [ 0 ] - 'a' ] = append ( d [ w [ 0 ] - 'a' ], w )
}
for _ , c := range s {
q := d [ c - 'a' ]
d [ c - 'a' ] = nil
for _ , t := range q {
if len ( t ) == 1 {
ans ++
} else {
d [ t [ 1 ] - 'a' ] = append ( d [ t [ 1 ] - 'a' ], t [ 1 :])
}
}
}
return
}
Solution 2
Python3 Java C++ Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class Solution :
def numMatchingSubseq ( self , s : str , words : List [ str ]) -> int :
d = defaultdict ( deque )
for i , w in enumerate ( words ):
d [ w [ 0 ]] . append (( i , 0 ))
ans = 0
for c in s :
for _ in range ( len ( d [ c ])):
i , j = d [ c ] . popleft ()
j += 1
if j == len ( words [ i ]):
ans += 1
else :
d [ words [ i ][ j ]] . append (( i , j ))
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 class Solution {
public int numMatchingSubseq ( String s , String [] words ) {
Deque < int []>[] d = new Deque [ 26 ] ;
Arrays . setAll ( d , k -> new ArrayDeque <> ());
for ( int i = 0 ; i < words . length ; ++ i ) {
d [ words [ i ] . charAt ( 0 ) - 'a' ] . offer ( new int [] { i , 0 });
}
int ans = 0 ;
for ( char c : s . toCharArray ()) {
var q = d [ c - 'a' ] ;
for ( int t = q . size (); t > 0 ; -- t ) {
var p = q . pollFirst ();
int i = p [ 0 ] , j = p [ 1 ] + 1 ;
if ( j == words [ i ] . length ()) {
++ ans ;
} else {
d [ words [ i ] . charAt ( j ) - 'a' ] . offer ( new int [] { i , j });
}
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 class Solution {
public :
int numMatchingSubseq ( string s , vector < string >& words ) {
vector < queue < pair < int , int >>> d ( 26 );
for ( int i = 0 ; i < words . size (); ++ i ) d [ words [ i ][ 0 ] - 'a' ]. emplace ( i , 0 );
int ans = 0 ;
for ( char & c : s ) {
auto & q = d [ c - 'a' ];
for ( int t = q . size (); t ; -- t ) {
auto [ i , j ] = q . front ();
q . pop ();
if ( ++ j == words [ i ]. size ())
++ ans ;
else
d [ words [ i ][ j ] - 'a' ]. emplace ( i , j );
}
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 func numMatchingSubseq ( s string , words [] string ) ( ans int ) {
type pair struct { i , j int }
d := [ 26 ][] pair {}
for i , w := range words {
d [ w [ 0 ] - 'a' ] = append ( d [ w [ 0 ] - 'a' ], pair { i , 0 })
}
for _ , c := range s {
q := d [ c - 'a' ]
d [ c - 'a' ] = nil
for _ , p := range q {
i , j := p . i , p . j + 1
if j == len ( words [ i ]) {
ans ++
} else {
d [ words [ i ][ j ] - 'a' ] = append ( d [ words [ i ][ j ] - 'a' ], pair { i , j })
}
}
}
return
}
Solution 3
Python3 Java C++ Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class Solution :
def numMatchingSubseq ( self , s : str , words : List [ str ]) -> int :
def check ( w ):
i = - 1
for c in w :
j = bisect_right ( d [ c ], i )
if j == len ( d [ c ]):
return False
i = d [ c ][ j ]
return True
d = defaultdict ( list )
for i , c in enumerate ( s ):
d [ c ] . append ( i )
return sum ( check ( w ) for w in words )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 class Solution {
private List < Integer >[] d = new List [ 26 ] ;
public int numMatchingSubseq ( String s , String [] words ) {
Arrays . setAll ( d , k -> new ArrayList <> ());
for ( int i = 0 ; i < s . length (); ++ i ) {
d [ s . charAt ( i ) - 'a' ] . add ( i );
}
int ans = 0 ;
for ( String w : words ) {
if ( check ( w )) {
++ ans ;
}
}
return ans ;
}
private boolean check ( String w ) {
int i = - 1 ;
for ( int k = 0 ; k < w . length (); ++ k ) {
int c = w . charAt ( k ) - 'a' ;
int j = search ( d [ c ] , i );
if ( j == d [ c ] . size ()) {
return false ;
}
i = d [ c ] . get ( j );
}
return true ;
}
private int search ( List < Integer > t , int x ) {
int left = 0 , right = t . size ();
while ( left < right ) {
int mid = ( left + right ) >> 1 ;
if ( t . get ( mid ) > x ) {
right = mid ;
} else {
left = mid + 1 ;
}
}
return left ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 class Solution {
public :
int numMatchingSubseq ( string s , vector < string >& words ) {
vector < vector < int >> d ( 26 );
for ( int i = 0 ; i < s . size (); ++ i ) d [ s [ i ] - 'a' ]. emplace_back ( i );
int ans = 0 ;
auto check = [ & ]( string & w ) {
int i = -1 ;
for ( char & c : w ) {
auto & t = d [ c - 'a' ];
int j = upper_bound ( t . begin (), t . end (), i ) - t . begin ();
if ( j == t . size ()) return false ;
i = t [ j ];
}
return true ;
};
for ( auto & w : words ) ans += check ( w );
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 func numMatchingSubseq ( s string , words [] string ) ( ans int ) {
d := [ 26 ][] int {}
for i , c := range s {
d [ c - 'a' ] = append ( d [ c - 'a' ], i )
}
check := func ( w string ) bool {
i := - 1
for _ , c := range w {
t := d [ c - 'a' ]
j := sort . SearchInts ( t , i + 1 )
if j == len ( t ) {
return false
}
i = t [ j ]
}
return true
}
for _ , w := range words {
if check ( w ) {
ans ++
}
}
return
}
GitHub