[leetcoide] 【字符串】28. Implement strStr()

Implement strStr().

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.


题意

两个字符串haystack和needle ,如果needle是haystack的子串,返回needle在haystack中出现的索引,如果needle不是haystack的子串,返回-1;

题解

可以暴力破解,就是逐一比较。这样的时间复杂度是O(M*N)
最好的方法是kmp算法,我这里推荐一篇非常简单明了的文章,我也是看这篇文章搞懂了kmp  

难点就是建立公共前后缀数组(next数组),
原理就是这样,但是代码实现过程也比较难理解,这里也简单介绍一下代码实现过程:
getNext中,next[i]为前i个字符里公共前后缀的个数减1(表示字符索引)。i从0到needle.length() - 1遍历,j为此时公共前后缀的个数减1(表示字符索引),
先说needle[i]==needle[j]的情况,此时索引0-j的字符与i-j到i-1的字符是相等的,判断第i个和第j+1个是否相等,相等则j+1

其次是needle[i]!=needle[j]的情况,这个情况比较难理解

图中黄色部分是相等的,因此

图中红色部分也是相等的。这样0-next[j]与i-next[j]到i也是相等的,这样循环找到最大公共前后缀,直到needle[j]==needle[i]或者next[j]=-1。

这样,就可以做出needle的next数组了。
最后就是needle和haystack匹配,匹配方法相同。

class Solution {
 public:
     
     int strStr(string haystack, string needle) {
         if (haystack.empty()) return needle.empty() ? 0 : -1;
         if (needle.empty()) return 0;
         vector<int> next(needle.length() + 1);
         getNext(next, needle);
         int i = 0, j =-1;
         for (i=0;i< haystack.length();i++) 
         {
             while (j != -1 && haystack[i] != needle[j+1]) 
                j = next[j];
            if(haystack[i]==needle[j+1])
                j++;
            if(j==needle.length()-1)
                return i-j;
             
         }
         return -1;
     }
     void getNext(vector<int> &next, string &needle) {
         int i = 0, j = -1;
         next[i] = j;
         for(i=1;i!=needle.length();i++) 
         {
             while (j != -1 && needle[i] != needle[j+1]) 
                j = next[j];
             if (needle[i] == needle[j+1]) j++; 
             next[i] = j;
         }
     }
 };


发布了83 篇原创文章 · 获赞 32 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章