这是一道比较简单的问题,就是找出母字符串中是否有与子字符串相匹配的字符串。
要注意的就是几点,题目中要求当needle串为空时,要返回0,没有匹配的则返回 -1.
下面是题目的具体描述,haystack代表长的,needle则代表短的。
暴力解法
暴力思想就是从头进行匹配。
class Solution {
public:
int strStr(string haystack, string needle) {
int m = haystack.size();
int n = needle.size();
int i,j;
if(m < n )
return -1;
if(n == 0)
return 0;
for(i = 0; i <= m-n ; i++)
{
for(j = 0; j < n; j++)
{
if(haystack[i+j] != needle[j])
{
break;
}
}
if(j == n)
return i;
}
return -1;
}
};
KMP解法
kmp 解法是解决字符串匹配的好方法,它的原理内容太多,我这里很难叙述清楚,这里仅仅是简单给出代码,有兴趣可以仔细研究一下:
class Solution {
public int strStr(String haystack, String needle) {
return kmp(haystack, needle);
}
private int kmp (String s1, String s2) {
if (s2.length() == 0) {
return 0;
}
if (s1 == null || s2 == null || s1.length() < s2.length()) {
return -1;
}
int[] next = new int[s2.length()];
next[0] = -1;
for (int i = 1, k = -1; i < s2.length();) {
if (k == -1 || s2.charAt(i - 1) == s2.charAt(k)) {
k++;
next[i] = k;
i++;
} else {
k = next[k]; // 这里是容易写错的地方,回溯递归
}
}
for (int num : next) {
System.out.print(num + " ");
}
System.out.println();
for (int i = 0, j = 0; i < s1.length();) {
if (s1.charAt(i) != s2.charAt(j)) {
if (next[j] == -1) {
i++;
j = 0;
} else {
j = next[j];
}
} else {
if (j == s2.length() - 1) {
return (i - s2.length() + 1);
}
i++;
j++;
}
}
return -1;
}
}
还可以对 kmp 进一步改进得到 next 的改进型 nextval 数组,代码如下,由于内容较多,这里也不过多解释,但是仅仅修改了上面得到 next 数组代码的一小部分内容:
class Solution {
public int strStr(String haystack, String needle) {
return kmp(haystack, needle);
}
private int kmp (String s1, String s2) {
if (s2.length() == 0) {
return 0;
}
if (s1 == null || s2 == null || s1.length() < s2.length()) {
return -1;
}
int[] nextval = new int[s2.length()];
nextval[0] = -1;
for (int i = 1, k = -1; i < s2.length();) {
if (k == -1 || s2.charAt(i - 1) == s2.charAt(k)) {
k++;
if (s2.charAt(i) == s2.charAt(k)) {
nextval[i] = nextval[k];
} else {
nextval[i] = k;
}
i++;
} else {
k = nextval[k];
}
}
// for (int num : nextval) {
// System.out.print(num + " ");
// }
// System.out.println();
for (int i = 0, j = 0; i < s1.length();) {
if (s1.charAt(i) != s2.charAt(j)) {
if (nextval[j] == -1) {
i++;
j = 0;
} else {
j = nextval[j];
}
} else {
if (j == s2.length() - 1) {
return (i - s2.length() + 1);
}
i++;
j++;
}
}
return -1;
}
}