[LeetCode]—Implement strStr() 寻找子串匹配第一个位置 (KMP)

Implement strStr()

 

Implement strStr().

Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.

分析:

         子串匹配问题。主要用该题巩固复习了一下KMP算法。

          先用BF方法,快速的完成一下:复杂度O(M*N)

         

class Solution {
public:
     char *strStr(char *haystack, char *needle) {
        int lh=strlen(haystack);
        int ln=strlen(needle);
        
         int i=0,j=0,start;
         if (ln==0)return haystack; 
         while((lh-i)>=ln){
            
          start=i;
          while(haystack[i++]==needle[j++]){
            if(j==ln)return &haystack[start];
          }
           i=start+1;
           j=0;
         }
         
         return NULL;
    }
};

再回去复习一下KMP算法:

        KMP算法的主要贡献在于:对目标串S的遍历可以一次到底,不用再进行回溯,只移动模式串T。

       主要依据:分析模式串T的自身特点,如果前缀和后缀有相等的部分,那么,在不等的情况下,只需要移动到前缀后一位和当前目标串S当前位比较。其中求数据Next[i] 是关键。Next[i] 数组表示对于模式串T,当前i位如果未匹配成功,就让Next[i](小于i的)位来匹配,相当于T移动。

       介绍KMP详细原理的文章有:http://blog.csdn.net/v_july_v/article/details/7041827

       求解Next[]数组方法清晰的文章有:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html

 

最后是我实现的KMP版本的求解:O(M+N)


class Solution {
public:
     char *strStr(char *haystack, char *needle) {
            if(strlen(needle)==0)return haystack; 
            int ind=KMP(haystack,needle);
            if(ind>0)return &haystack[ind-1];
            return NULL;
      } 

private:
    int KMP(const char *S,const char *T){ //返回的是位置,不是下标
        int len_S=strlen(S);
        int len_T=strlen(T);
        int i=0,j=0;
        
        int *next=(int *)malloc(sizeof(int)*len_T);
        Next(next,T);
        
        while(i<len_S && j<len_T ){
            if(j==-1 || S[i]==T[j])
                i++,j++;
            else
                j=next[j];
        }

        if(j>=len_T) 
                return (i-len_T+1);
        else
                return -1;

    }

    void Next(int *next,const char *T){
         int len_T=strlen(T);
          assert(len_T>0);   //len_T=0,退出
         
         next[0]=-1;
         int i=0,k=-1;
         while(i<len_T-1)
         {
            if(k==-1 || T[i]==T[k]){
                k++;
                i++;
                next[i]=k;
            }else
                k=next[k];
         } 
    }
    
};


求next数组是可以由优化的,有时间也还可以继续研究下 Boyer-Mooer算法和Rabin-Karp算法。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值