• LeetCode: Implement strStr() [027]


    【题目】


    Implement strStr().

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


    【题意】

    实现库函数strStr(), 功能是在字符串haystack中找出目标串needle第一次出现的索引位


    【思路】

    字符串的匹配,能够用暴力解法,但不推荐。一般使用KMP算法求解。

    简要介绍一下KMP的思想:

        haystack是题设所给的匹配串,needle是题设所给的模式串。

        needle在和haystack匹配时,假设遇到某个位置上的字符失配,暴力法会将needle的游标返回头部,从头開始又一次匹配;而KMP算法同意游标不返回头部,而利用已有的匹配结果,将游标移动到新的位置k上,从k位置開始匹配。      
        怎样确定这个新位置,或者说这个新位置是什么呢?
       (1).我们这么来看,如果在当前的匹配过程中发现haystack[i]!=needle[j],显然这个时候haystack[i-j, i-1]和needle[0,j-1]各个位置上的字符已经匹配。
       (2).此时,needle新的游标位置next[j]=k,它满足子串needle[0,k-1]与子串needle[j-k,j-1]全然匹配,也就是说字符串needle[0,j-1]的前k个字符与后k个字符同样。【k是满足该匹配条件的最大值,且k<j】
       (3)把needle的游标从j移动到k,意味着我们从k開始比較就能够了,needle[0,k-1]不须要再反复比較了。这一点由(1)保证。

            

        结合(1)(2)我们有:haystack[i-j, i-1]=needle[0,j-1] && needle[0,k-1]=needle[j-k, j-1] 

        显然我们能够推出:needle[0,k-1]=haystack[i-k,i-1]; 也即从k位置開始比較就可以,不须要从头開始匹配。
            
        
        KMP算法关键在于建立next数组,即发生不匹配情况是回跳到哪个位置继续匹配。
        如果我们已经确定了needle字符串中j位置的字符失配时跳转的位置是k,即next[j]=k, 依据上面的分析我们知道此时满足needle[0,k-1]=needle[j-k, j-1]。那next[j+1]=?
        1. 假设needle[k]==needle[j],显然有needle[0,k]=needle[j-k, j],则next[j+1]=k+1;
        2. 假设needle[k]!=needle[j], 这也是一种失配的情况(即needle起始字符串和结尾字符串匹配时发生失配),则游标k应该跳转到next[k],然后再与needle[j]比較,假设还是失配,游标继续通过next数组回跳,直至与needle[j]匹配,此时next[j+1]=k+1;


    【代码】

    class Solution {
    public:
        void getNext(char*needle, int*next){
            int size=strlen(needle);
            int i=0,k=-1;
            next[0]=-1;
            while(i<size-1){        //由于我们通过A[i]来求A[i+1]的,因此结束条件是i<size-1
                if(k==-1||needle[i]==needle[k]){
                    i++;
                    k++;
                    next[i]=k;
                }
                else{
                    k=next[k];
                }
            }
        }
        char *strStr(char *haystack, char *needle) {
            if(needle==NULL || haystack==NULL)return NULL;
            int patternSize=strlen(needle);
            int haystackSize=strlen(haystack);
            int*next=new int[patternSize];
            //生成next数组
            getNext(needle,next);
            //匹配
            int i=0;    //haystack的游标
            int j=0;    //needle的游标
            while(i<haystackSize&&j<patternSize){
                if(j==-1||haystack[i]==needle[j]){
                    i++;j++;
                }
                else{
                    j=next[j];
                }
            }
            delete next;
            if(j==patternSize)return haystack+i-j;
            return NULL;
        }
    };


  • 相关阅读:
    用来武装Firebug的十三款Firefox插件
    五分钟搭建 Flash 视频直播站
    最新2010虎年元旦祝福短信
    Firefogg:轻松编码 OGG 视频
    winform编程DataGridView控件的使用总结
    flex实现的播放器
    flex学习笔记2
    jQuery 1.4 正式版发布
    开源路由器第三方固件openwrt衍生版xwrt
    Adobe Audition(Cool Edit)简易教程
  • 原文地址:https://www.cnblogs.com/blfshiye/p/3761630.html
Copyright © 2020-2023  润新知