题目:
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.
题解:
Leetcode说Interview的时候用Brute Force即可,不知是真是假。Anyway,用KMP算法做一做,顺便复习一下。
假设要在long里找short,KMP算法的思想是:
1. 如果short的第j个字符与long出现了不匹配,则意味着0...j-1个都匹配。假设此时匹配到了long的第i个字符。
2. 如何决定short的跳距离呢?计算short的Longest prefix/suffix (lps) matching。
如:short: ABABA
则 lps[0] = 0, lps[1] = 0, lps[2] = 1 (A == A), lps[3] = 2 (AB == AB), lps[4] = 3 (ABA = ABA)
3. 则当short[j] 与 long[i] 不匹配时,应将j更新为lps[j-1]的值,如:
long: ABABDABABA short: ABABA
ABABDABABA
ABABA
i = 4, long[i] = 'D', j = 4, short[j] = 'A', long[i] != short[j],
当j!= 0 时(已经比较多于一个字符),j更新为lps[j-1] = lps[3] = 2.即long[i] = ‘D’直接与short[2]= 'A'比较,因为更新后,j之前的字符("AB")必然与long中i之前的字符("AB")匹配。当j ==0时(才比较第一个),i = i + 1,即short只向右移动一位。
4. 当j == short.length的时候,完全匹配,这时候输出的index = i - j。
C++版:
class Solution {
public:
int strStr(char *haystack, char *needle) {
//Compute the Longest Prefix Suffix table (lps[]) for the needle.
int length = strlen(needle);
int mainLength = strlen(haystack);
if((!mainLength && length) || (length > mainLength))
return -1;
if(!length)
return 0;
int* lps = new int[length];
computeLPS(needle, lps, length);
int i = 0, j = 0;
while(i < mainLength) {
if(needle[j] == haystack[i]) {
i++;
j++;
}
if(j == length) {
return i - j;
}
else if(i < mainLength && haystack[i] != needle[j]) {
if(j)
j = lps[j-1];
else
i++;
}
}
delete [] lps;
return -1;
}
void computeLPS(char *needle, int* lps, int length) {
//needle = "AABAACAABAA"
//lps = [0, 1, 0, 1, 2, 0, 1, 2, 3, 4, 5]
int currentLongest = 0;
//The first char will always have zero length longest true prefix/suffix matching.
lps[0] = 0;
//A way to compute the lps from geeksforgeeks.com. Never be able to write it by my own.
for(int j = 1; j < length; j++) {
if(needle[j] == needle[currentLongest]) {
currentLongest++;
lps[j] = currentLongest;
} else {
if(currentLongest) {
currentLongest = lps[currentLongest-1];
j--;
} else
lps[j] = 0;
}
}
}
};
Java版:
public class Solution {
public int strStr(String haystack, String needle) {
if(haystack.length() == 0 && needle.length() != 0)
return -1;
if(haystack.length() < needle.length())
return -1;
if(needle.length() == 0)
return 0;
List<Integer> lps = new ArrayList<Integer>();
lps.add(0);
int currentLongest = 0;
for(int i = 1; i < needle.length(); i++) {
if(needle.charAt(i) == needle.charAt(currentLongest)) {
currentLongest++;
lps.add(currentLongest);
} else {
if(currentLongest != 0) {
currentLongest = lps.get(currentLongest-1);
i--;
} else {
lps.add(0);
}
}
}
int j = 0, k = 0;
while(j < haystack.length()) {
if(haystack.charAt(j) == needle.charAt(k)) {
j++;
k++;
}
if( k == needle.length() ) {
return j - k;
}
if( j < haystack.length() && haystack.charAt(j) != needle.charAt(k) ) {
if(k != 0) {
k = lps.get(k-1);
} else {
j++;
}
}
}
return -1;
}
}
Python版: