392. Is Subsequence

Given a string s and a string t, check if s is subsequence of t.

You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not).

Example 1:
s = "abc", t = "ahbgdc"

Return true.

Example 2:
s = "axc", t = "ahbgdc"

Return false.

Follow up:
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?






https://leetcode.com/problems/is-subsequence/discuss/87254/Straight-forward-Java-simple-solution

Solution 1 : 

// time : t.length() + s.length()
// space : 1 

class Solution {
    public boolean isSubsequence(String s, String t) {
        int i = 0;
        for(char c : t.toCharArray()){
            if(i < s.length() && s.charAt(i) == c) i++;
        }
        return i == s.length();
    }
}










Follow up : 
If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?


using binary search, and greedily choose the smallest starting index and the  smallest larger than index , because 

Sequence : aed 
a                              a          Ed 
Index : 1         Index : 7 



If index 7 a can form sequence AED, then index 1 can form sequence AED for sure, since index 1 is before index 7 





 // Follow-up: O(N) time for pre-processing, O(Mlog?) for each S.
    // Eg-1. s="abc", t="bahbgdca"
    // idx=[a={1,7}, b={0,3}, c={6}]
    //  i=0 ('a'): prev=1
    //  i=1 ('b'): prev=3
    //  i=2 ('c'): prev=6 (return true)


    // Eg-2. s="abc", t="bahgdcb"
    // idx=[a={1}, b={0,6}, c={5}]
    //  i=0 ('a'): prev=1
    //  i=1 ('b'): prev=6
    //  i=2 ('c'): prev=? (return false)

your helper function binarySearch finds the first element of list that is greater than or equal to the index that is passed in. Is my understanding correct

Yes. You are right. Since we always need to move forward in t regarding the index, thus we have to find out the very first character in that is the same with the current character we are considering in s. Then we set our prev (which is the start index of substring in t) to prev++.





 
https://leetcode.com/problems/is-subsequence/discuss/87302/Binary-search-solution-for-follow-up-with-detailed-comments
 
// time : t.length() + # of s * s.length() * log(freq of chars in the t)
// space : hashmap : length of the t 


// use binary search 
// preprocess the string t, to get every char’s index 
// so every time we check if the incoming word is a subsequence of t, we can just check if the char in the incoming string can be found in the t, in the HashMap , in order 

// use binary search to find the smallest larger than prev char’s  index  possible for each char 

class Solution{
    public boolean isSubsequence(String s, String t) {
        if(s == null || t == null) return false;
        
        Map<Character, List<Integer>> map = new HashMap<>();
        
        // preprocess t 
        for(int i = 0; i < t.length(); i++){
            char c = t.charAt(i);
            if(!map.containsKey(c)){
                map.put(c, new ArrayList<>());
            }
            map.get(c).add(i);
        }
        
        int prev = -1; // index of prev char of s in t 
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            if(map.get(c) == null){
                return false;
            }else{
                List<Integer> list = map.get(c);
                prev = bs(prev, list, 0, list.size() - 1);
                if(prev == -1){
                    return false;
                }
                prev++;
            }
        }
        return true;
    }
    
    private int bs(int index, List<Integer> list, int start, int end){
        while(start <= end){
            int mid = start + (end - start) / 2;
            if(list.get(mid) < index){
                start = mid + 1;
            }else{
                end = mid - 1;
            }
        }
        return start == list.size() ? -1 : list.get(start);
    }
    
}




// use tree map , same function as binary search 

class Solution {
    public boolean isSubsequence(String s, String t) {
        HashMap<Character, TreeSet<Integer>> map = new HashMap<>();
        for(int i = 0; i < t.length(); i++){
            TreeSet<Integer> set = map.get(t.charAt(i));
            if(set == null){
                set = new TreeSet<>();
                map.put(t.charAt(i), set);
            }
            set.add(i);
        }
        int prev = -1;
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            TreeSet<Integer> set = map.get(c);
            if(set == null) return false;
            if(prev == -1){
                prev = set.first();
            }else{
                Integer tmp = set.higher(prev);
                if(tmp == null) return false;
                prev = tmp;
            }
        }
        return true;
        
    }
}

 

 

0 3 5 7 ide

 

Prev = 4 this

Smallest larger or equal is 5 spa

 

If prev = 8, return -1 code

相關文章
相關標籤/搜索