【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; } };