strStr

strstr (a.k.a find sub string), is a useful function in string operation. Your task is to implement this function.

For a given source string and a target string, you should output the firstindex(from 0) of target string in source string.

If target does not exist in source, just return -1.

Have you met this question in a real interview? 
Yes
Example

If source = "source" and target = "target", return -1.

If source = "abcdabcdefg" and target = "bcd", return 1.

Challenge

O(n2) is acceptable. Can you implement an O(n) algorithm? (hint: KMP)

Clarification

Do I need to implement KMP Algorithm in a real interview?

  • Not necessary. When you meet this problem in a real interview, the interviewer may just want to test your basic implementation ability. But make sure your confirm with the interviewer first.

題目至少有3種方法,第一種是暴力搜索,每次移動一步,則時間複雜度爲O(nm),其中n表示source的長度,m表示target的長度。第二種方法是在第一種方法的基礎上做了改進,每次對比時,同時從兩邊向中間夾,這樣可以適當降低時間複雜度;第三種方法,肯定就是KMP了,KMP算法優化的是第一二種方法存在的回溯問題,第一二種方法中,每次移動i到達某個值,使得source[i] != target[j]的時候,會回溯到i - j + 1的位置,也就是說[i-j+1, i]這個區間又要重複計算;

KMP算法的提出就是要避免此回溯,使得i只往後移,也就是說,這樣的時間複雜度將是O(N),N爲source的長度。KMP的算法證明,就不詳細展開了;這裏主要講下next[j]的求解,其實在求解next[j]的過程有遞歸的含義在其中,也是在做一個字符串的匹配問題,有兩個變量k,j,分別初始化爲k = -1, j = 0,next[0] = -1;當k == -1 或者 target[k] == target[j]的時候,則說明next[j + 1] = k + 1; 否則的話,則將k移動到next[k],這一步就包括了遞推的字符串匹配在其中,理解起來比較難;

class Solution {
public:
    /**
     * Returns a index to the first occurrence of target in source,
     * or -1  if target is not part of source.
     * @param source string to be scanned.
     * @param target string containing the sequence of characters to match.
     */
    //KMP算法
    void GetNext(const char *p, vector<int> &next)
    {
        int len = strlen(p);
        int k = -1, j = 0;
        while(j < len - 1)
        {
            if(k == -1 || p[k] == p[j])
            {
                next[++j] = ++k;
            }
            else
                k = next[k];
        }
    }
    
    
    int strStr(const char *source, const char *target) {
        // write your code here
        if(source == NULL || target == NULL)
            return -1;
        int lens = strlen(source);
        int lent = strlen(target);
        if(lens < lent)
            return -1;
        int i = 0, j = 0;
        vector<int> next(lent, -1);
        GetNext(target, next);
        while(i < lens && j < lent)
        {
            if(j == -1)
            {
                ++i;
                j = 0;
            }
            else if(source[i] == target[j])
            {
                ++i;
                ++j;
            }
            else 
            {
                j = next[j];
            }
        }
        
        if(j >= lent)
            return i - j;
        return -1;
    }
};

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章