LeetCode ImplementStrstr
class Solution { public: char *strStr(char *haystack, char *needle) { if (haystack == NULL || needle == NULL) return NULL; int wpos[256]; char cur = 0; int len = 0; for (int i=0; i < 256; i++) wpos[i] = -1; for (int i=0; (cur = needle[i]) != '\0'; i++, len++) wpos[cur] = i; int p = 0, q = 0; while (true) { while (haystack[p] != '\0' && needle[q] != '\0' && haystack[p] == needle[q]) p++, q++; if ( needle[q] == '\0') { return haystack + p - q; } if (haystack[p] == '\0') { return NULL; } int npos = p - q + len; int move = wpos[haystack[npos]]; q = 0; if (move < 0) { p++; } else { p = npos - move; } } return NULL; } };
又写了次sunday算法,还是磕磕碰碰
第二轮 3.21
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
kmp、sunday都想不起来了,直接暴力吧,超时,然后加上一些条件能过应该是testcase不好,否则还是应该能造成超时:
class Solution { public: int strStr(char *haystack, char *needle) { if (haystack == NULL || needle == NULL) { return -1; } int hlen = strlen(haystack); int nlen = strlen(needle); if (nlen > hlen) { return -1; } int hi = 0; int ni = 0; while (hi < (hlen - nlen + 1)) { int ti = hi; ni = 0; // try to campare start from haystack[ti] & needle[ni] (ti=hi, ni=0) while (needle[ni] != '\0' && haystack[ti] != '\0') { if (needle[ni] == haystack[ti]) { ni++, ti++; } else { break; } } if (needle[ni] == '\0') { return hi; } // start from next char hi++; } // not found return -1; } };
下面就超时:
class Solution { public: int strStr(char *haystack, char *needle) { if (haystack == NULL || needle == NULL) { return -1; } for (int i=0; true; i++) { int ci = i; int ni; for(ni = 0; needle[ni] && haystack[ci]; ni++, ci++) { if (needle[ni] != haystack[ci]) { break; } } if (needle[ni] == '\0') { return i; } if (haystack[i] == '\0') { break; } } // not found return -1; } };
下面又不超时,到底是为什么?不是一样的方式么
class Solution { public: int strStr(char *haystack, char *needle) { int i,j; for (i = j = 0; haystack[i] && needle[j];) { if (haystack[i] == needle[j]) { ++i; ++j; } else { i = i - j + 1; j = 0; } } return needle[j] ? -1 : (i - j); } };
一次Sunday算法:
#include <stdio.h> #include <stdlib.h> #include <string.h> int sunday(const char* src, const char* pattern) {
if (src == NULL || pattern == NULL) return -1; int slen = strlen(src); int plen = strlen(pattern); int cpos = 0; int dict[256] = {0}; memset(dict, -1, sizeof(dict)); for (int i=0; i<plen; i++) { dict[pattern[i]] = i; } while (cpos + plen <= slen) { int i = 0; while (i < plen) { if (src[i+cpos] != pattern[i]) { break; } i++; } if (i == plen) { return cpos; } int move = dict[src[cpos + plen]]; // printf("tail char: %c\n", pattern[cpos + plen]); if (move < 0) { cpos = cpos + plen; } else { cpos = cpos + plen - move; } // printf("next pos:%d, %c\n", cpos, src[cpos]); } return -1; } int main(int argc, char* argv[]) { if (argc < 3) { printf("%s <src string> <pattern string>\n", argv[0]); return 0; } int idx = sunday(argv[1], argv[2]); if (idx < 0) { printf("not found pattern in src string\n"); return 0; } printf("match idx: %d, string from: %s\n", idx, argv[1] + idx); return 0; }
可以再简化代码:
#include <iostream> #include <cstdlib> int sunday(const char* pattern, const char* str) { if (pattern == NULL || str == NULL) { return -1; } int slen = 0, plen = 0; while (pattern[plen] != '\0') plen++; while (str[slen] != '\0') slen++; int tbl[128]; for (int i=0; i<128; i++) tbl[i] = -1; for (int i=0; i<plen; i++) tbl[pattern[i]] = i; int pi = 0, si = 0; while (si < slen) { while (str[si] == pattern[pi] && si < slen) si++, pi++; if (pi == plen) return si - plen; int nidx = plen - pi + si; int offset = tbl[str[nidx]]; si = nidx - offset; pi = 0; } return -1; } int main() { char* pattern = "simple"; char* str = "the example is a simple example."; int idx = sunday(pattern, str); if (idx < 0) { printf("not found\n"); } else { printf("found at: %d\n", idx); printf("str:%s\n", str + idx); } system("pause"); return 0; }
si = nidx - offset;
这里当offset是负数时和非负数时其实是两种情况,但是因为将tbl数组初始化了为-1,所以nidx-offset其实相当于nidx + 1,刚刚可以把两种情况统一了。
感觉前面的暴力法写的复杂了,思路可以再清晰一些:
class Solution { public: int strStr(string haystack, string needle) { int hlen = haystack.size(); int nlen = needle.size(); for (int i=0; i<hlen; i++) { int p = i, q = 0; if (hlen - i < nlen) { return -1; } while (p < hlen && q < nlen && haystack[p] == needle[q]) p++, q++; if (q == nlen) { return i; } } return nlen == 0 ? 0 : -1; } };