首页 > 代码库 > Implement strStr()
Implement strStr()
Implement strStr().
Returns a pointer to the first occurrence of needle in haystack, or null if needle is not part of haystack.
方法一:暴力破解,O(mn),超时,写了这段代码,估计面试直接出局。
1 class Solution { 2 public: 3 char *strStr(char *haystack, char *needle) { 4 if( !haystack || !needle ) return 0; 5 while( *haystack ) { 6 char* p1 = haystack; 7 char* p2 = needle; 8 while( *p1 && *p2 && *p1 == *p2 ) ++p1, ++p2; 9 if( !*p2 ) return haystack;10 ++haystack;11 }12 return 0;13 }14 };
方法二:对上面进行优化,AC
1 class Solution { 2 public: 3 char *strStr(char *haystack, char *needle) { 4 if( !haystack || !needle ) return 0; 5 if( !*needle ) return haystack; 6 int len1 = strlen(haystack); 7 int len2 = strlen(needle); 8 for(int i=0; i+len2<=len1; ++i) { //保证i后面的字符串长度>=needle的长度 9 if( haystack[i] != *needle ) continue; //第一个字母不匹配,跳过10 char* p1 = haystack+i;11 char* p2 = needle;12 while( *p1 && *p2 && *p1 == *p2 ) ++p1,++p2;13 if( !*p2 ) return haystack+i;14 }15 return 0;16 }17 };
方法三:KMP算法,关键在于理解和求next数组。假设pattern字符串为p0p1p2p3....pn-1,长度为n,那么有
当 j = 0 时,next[j] = -1
当存在 max{ k | 0 < k < j 且 ‘p0p1p2...pk-1‘ = ‘pj-k...pj-1‘ } 时,next[j] = k
其他情况 next[j] = 0
j 0 1 2 3 4 5 6
pattern a b a a b c a
next[j] -1 0 0 1 1
这里要求next[5] ,首先看子串p0p1p2p3p4 = abaab,我们发现 p0p1 = ab ,p3p4 = ab,此时k = 2,那么next[5] = 2,即当pattern[5]不匹配时,那么pattern[3..4]是匹配的,而pattern[0..1] = pattern[3..4],故下次应该匹配的字符应该是pattern[2],其下标也就是next[5]的值
如何求解next[j]的值?
假设已经知道 next[j-1] = k,那么说明当pattern[j-1]不匹配的时候,那么应该与pattern[k]比较,也告诉我们 ‘p0p1p2...pk-1‘ = ‘pj-k-1...pj-2‘
如果 pk = pj-1 ,那么就有 ‘p0p1p2...pk-1pk‘ = ‘pj-k-1...pj-2pj-1‘ ,说明当pattern[j]不匹配时,那么可以与pattern[k+1]比较,即next[j] = k+1 = next[j-1]+1
如果 pk != pj-1,那么说明 ‘p0p1p2...pk-1pk‘ != ‘pj-k-1...pj-2pj-1‘ ,需要继续需找匹配的最长前缀和后缀,需找的方法如下:
1. k = next[j-1],比较pk 与 pj-1,若相等,那么next[j] = next[j-1] + 1,若不等转2
2. k1 = next[k],继续比较pk1 与 pj-1,若相等那么next[j] = next[k] + 1,若不等转3
3. k2 = next[k1],继续比较pk2 与 pj-1,若相等那么next[j] = next[k1] + 1,若不等转...
......
n. kn = next[kn-1],假设此时pkn = pj-1,那说明 ‘p0p1...pkn‘ = ‘pj-kn-1...pj-1‘,那么如果pattern[j]不匹配,可于pattern[kn+1]匹配,即next[j] = next[kn-1] + 1 = kn + 1;
注:若最后依然没有找到相等的,即kn = -1,此时next[j] = 0
代码如下:
1 class Solution { 2 public: 3 vector<int> getNext(char *str) { 4 int len = strlen(str); 5 vector<int> next(len, 0); 6 next[0] = -1; //初始化 7 for(int i=1; i<len; ++i) { //主要思路请看讲解 8 int k = next[i-1]; 9 while( k!=-1 && str[k] != str[i-1] ) k = next[k]; //k=-1或找到pk == pi-1时终止10 next[i] = k+1;11 }12 return next;13 }14 15 char *strStr(char *haystack, char *needle) {16 if( !haystack || !needle ) return 0;17 if( !*needle ) return haystack;18 vector<int> next = getNext(needle);19 int i=0, j=0;20 while( haystack[i] && needle[j] ) {21 if( haystack[i] == needle[j] ) { //如果相等,ij同时后移22 ++i,++j;23 }24 else { //不等25 j = next[j]; //haystack[i] 应该与 needle[j]比较26 if( j==-1 ) ++i, j=0; //如果j为-1,说明haystack[i]不存在needle中,那么直接跳过27 }28 }29 if( !needle[j] ) return haystack+i-j; //如果j指向末尾了,说明找到了30 else return 0;31 }32 };
Implement strStr()