您的位置:首页 > 其它

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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode KMP strStr