LeetCode 28: Implement strStr()
2015-10-23 00:13
369 查看
Implement strStr()
Implement strStr().Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
解题思路
字符串模式匹配问题,主要有两种算法。思路一:朴素的模式匹配 —— B-F 算法
该算法从目标串的第0个字符开始和模式串的第0个字符比较,如果相等,则继续逐个比较后续字符;否则从目标串的下一个字符起再重新和模式串的第0个字符比较。直到找到匹配字符串,或者目标串已经达到最后可能与模式串匹配的位置但是匹配失败。该算法在最坏情况下总的比较次数为 (lengthT−lengthP+1)∗lengthP。代码如下:
class Solution { public: int strStr(string haystack, string needle) { int len1 = haystack.length(), len2 = needle.length(); for (int i = 0; i <= len1 - len2; ++i) { int j = 0; for (; j < len2; ++j) { if (haystack[i+j] != needle[j]) break; } if (j == len2) return i; } return -1; } };
思路二:模式匹配的改进算法 —— KMP 算法
造成朴素模式匹配算法速度慢的原因是对目标串 T 的访问发生了“回溯”,而这些回溯是可以避免的。在第 s 趟比较失配时,目标串 T 的扫描指针 posT 不需要回溯, 算法下一趟比较从失配位置 posT 处继续向下比较;而在模式串 P 中,将扫描指针 posPj回退到 posPk 位置。对于不同的 j,k 的取值仅依赖于模式串 P 中 j (j从0开始编号) 位置之前的 j 个字符,与目标串无关。可以证明 KMP 算法的时间复杂度为O(lengthT+lengthP)。
next[] 数组:next[j] 表示模式串 P 中第 j 个字符与目标串 T 中相应字符失配时,P 中应当由哪个字符与 T 中刚失配的字符重新继续进行比较。如何正确的计算出 next[] 数组是实现 KMP 算法的关键。设模式串 P=p0p1…pm−2pm−1,则它的 next[] 数组定义如下:
next[j]=⎧⎩⎨−1,k,0,若 j == 0若0<k<j−1且k是使p0p1…pk−1=pj−kpj−k+1…pj−1 的最大整数其他情况
计算 next[j] 就是要在串 p0p1…pj−1中找出最长的、相等的前缀子串 p0p1…pk−1 和后缀子串 pj−kpj−k+1…pj−1。可以用递推的方法求 next[j] 的值。设已有 next[j] = k, 则有:
当 pk=pj 时,则 next[j+1]=next[j]+1;
当 pk!=pj 时,此时可以在 p0p1…pk−1 中寻找使的 p0p1…ph−1=pk−hpk−h+1…pk−1 的 h:
找到 h ,即 next[k]=h,此时有 p0p1…ph−1=pk−hpk−h+1…pk−1=pj−hpj−h+1…pj−1 ,即在 p0p1…pj−1 中找到了长度为h 的相等的前缀子串和后缀子串。此时:
若 ph=pj ,则有 next[j+1]=h+1=next[k]+1=next[next[j]]+1;
若 ph!=pj ,则该步骤,直到 next[t]=−1 才算失败;
找不到 h ,这时有 next[k]=−1。
代码如下:
class Solution { public: int strStr(string haystack, string needle) { int len1 = haystack.length(), len2 = needle.length(); // 求 next[] 数组 int next[len2]; int j = 0, k = -1; next[0] = -1; while (j < len2) { if (k == -1 || needle[j] == needle[k]) { j++; k++; next[j] = k; } else { k = next[k]; } } // 利用 next[] 数组进行模式匹配 int hPos = 0, nPos = 0; while (hPos < len1 && nPos < len2) { if (nPos == -1 || haystack[hPos] == needle[nPos]) { hPos++; nPos++; } else { nPos = next[nPos]; } } if (nPos == len2) return hPos - len2; return -1; } };
相关文章推荐
- PHP strstr 函数判断字符串是否否存在的实例代码
- KMP算法的C#实现方法
- JavaScript中数据结构与算法(五):经典KMP算法
- php中strstr、strrchr、substr、stristr四个函数的区别总结
- PHP用strstr()函数阻止垃圾评论(通过判断a标记)
- php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
- php strstr查找字符串中是否包含某些字符的查找函数
- leetcode 179 Largest Number
- leetcode 24 Swap Nodes in Pairs
- leetcode 2 Add Two Numbers 方法1
- leetcode 2 Add Two Numbers 方法2
- [LeetCode]47 Permutations II
- [LeetCode]65 Valid Number
- [LeetCode]123 Best Time to Buy and Sell Stock III
- [LeetCode] String Reorder Distance Apart
- [LeetCode] Sliding Window Maximum
- [LeetCode] Find the k-th Smallest Element in the Union of Two Sorted Arrays
- [LeetCode] Determine If Two Rectangles Overlap
- [LeetCode] A Distance Maximizing Problem
- leetcode_linearList