zoukankan      html  css  js  c++  java
  • 【Implement strStr() 】cpp

    题目

    Implement strStr().

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

    Update (2014-11-02):
    The signature of the function had been updated to return the index instead of the pointer. If you still see your function signature returns a char * or String, please click the reload button  to reset your code definition.

    代码

    class Solution {
    public:
        int strStr(string haystack, string needle) {
            const size_t len_hay = haystack.size();
            const size_t len_nee = needle.size();
            if ( len_hay < len_nee ) return -1;
            bool if_match = true;
            for ( size_t i = 0; i <= len_hay-len_nee; ++i )
            {
                if_match = true;
                for ( size_t j = 0; j < len_nee; ++j ){
                    if (haystack[i+j]!=needle[j]){
                        if_match = false;
                        break;
                    }
                }
                if ( if_match ){
                    return i;
                }
            }
            return -1;
        }
    };

    Tips:

    利用标志变量,暴力解决方法。时间复杂度O(m×n),空间复杂度O(1)

    貌似还有个KMP算法,这个可以做到O(m+n)的时间复杂度,但是空间复杂度牺牲到了O(m)。明天再看KMP算法,这个效率的提升还是蛮高的,直接提高到了线性复杂度。

    =========================================================================

    这个blog讲解kmp算法挺详细的

    http://blog.csdn.net/v_july_v/article/details/7041827

    结合上面的blog,弄明白kmp算法,总结起来就是两点:

    1. 弄明白next这个数组是怎么得来的。

    2. 弄明白如何利用next数组不让haystack的指针回溯的

    代码:

    class Solution {
    public:
        int strStr(string haystack, string needle) {
            int *next = new int[needle.length()];
            Solution::getNext(needle,next);
            size_t i = 0;
            size_t j = 0;
            while ( i<haystack.length() && j<needle.length() ){
                if ( haystack[i]!=needle[j] ){
                    if ( next[j]==-1 ){
                        j=0;
                        ++i;
                    }
                    else{
                        j = next[j];
                    }
                }
                else{
                    ++i;
                    ++j;
                }
            }
            return j==needle.length() ? i-j : -1;
        }
        static void getNext(std::string needle, int next[])
        {
            int k = -1;
            next[0] = k;
            int len = needle.length();
            int j = 0;
            while ( j<len-1 ){
                if ( k==-1 || needle[j]==needle[k] ){
                    ++k;
                    ++j;
                    if ( needle[j]==needle[k] ){
                        next[j] = next[k];
                    }
                    else{
                        next[j] = k;
                    }
                }
                else{
                    k = next[k];
                }
            }
        }
    };

    KMP这个算法非常精妙,总的来说就是不回溯haystack上的指针i,只移动needle上的指针j。

    http://www.ituring.com.cn/article/59881

    这片讲KMP的blog图画的好。 

    ==================================================================

    AC之后又回顾了整个过程,个人总结两个理解的关键点如下:

    (1)

    getNext中的k和j各代表什么含义?

    k:不断迭代中,needle[j]之前所有元素中(不包括needle[j]),可能满足条件的最大匹配前后缀的长度(0~k-1)。这里的“条件”指的是needle[j]=needle[k]。

    (2)

    又想到一个问题,为什么当needle[j]!=needle[k]的时候,k=next[k]而不是--k? 

    原因在下面的日志中找到了(http://blog.csdn.net/thisinnocence/article/details/38544719

    截取片段的红字部分是理解的关键,道理也是这个道理,但自己没有总结的这么精炼,所以直接截图引用了。

    至此,KMP这个算法的序列就结束了。算法的一些细节算是吃透了,以后再巩固。

    ====================================================

    第二次过这道题,直接放弃了KMP等算法,这个知道有就好了;只写了一个暴力解决的算法。

    class Solution {
    public:
        int strStr(string haystack, string needle) {
                if ( haystack.size()<needle.size() ) return -1;
                if ( needle.size()==0 ) return 0;
                for ( int i=0; i<haystack.size()-needle.size()+1; ++i )
                {
                    if ( haystack[i]==needle[0] )
                    {
                        bool find = true;
                        for ( int j=1; j<needle.size(); ++j )
                        {
                            if ( haystack[i+j]!=needle[j] ) { find=!find; break; }
                        }
                        if ( find ) { return i; }
                    }
                }
                return -1;
        }
    };
  • 相关阅读:
    C语言清空输入缓冲区的N种方法对比(转)
    UNIX网络编程——socket的keep-alive(转)
    UNIX网络编程——套接字选项(心跳检测、绑定地址复用)(转)
    UNIX网络编程——客户/服务器心搏函数 (转)
    TCP心跳 | TCP keepAlive(转)
    linux下使用adb查看android手机的logcat
    linux 常用查看设备命令(转)
    Spring AOP 详解
    HDU 2222 AC自动机 裸题
    大声说出我爱你—英语发音学习总结
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4474888.html
Copyright © 2011-2022 走看看