模式匹配算法
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
题目链接:https://leetcode-cn.com/classic/problems/implement-strstr/description/
参考《大话数据结构》第五章
KMP算法就是为了不必要的回溯不发生。
一、朴素的模式匹配算法
最好情况:每次都是首字母不匹配,O(m+n)
最坏情况:每次都是最后字母不匹配,O(m*(n-m+1))
int strStr(string haystack, string needle) {
int i = 0, j = 0;
if (haystack.length() < needle.length())
return -1;
if (needle == "")
return 0;
while (i < haystack.length() && j < needle.length())
{
if (haystack[i] == needle[j])
{
i++;//如果匹配,移到下一个字符。
j++;
}
else
{
i = i - j + 1;//如果不匹配,haystack字符移到下一位
j = 0;//needle从头开始进行下一轮比较
}
}
if (j == needle.length())
{
return i - needle.length();
}
else
{
return -1;
}
}
二、KMP模式匹配算法
若T的长度为m,get_next()时间复杂度O(m);
i不回溯,strStr()复杂度O(n);
整体复杂度O(m+n)。
void get_next(string T, int* next)
{
int i = 1;
int j = 0;
next[1] = 0;
while (i < T.length())
{
if (j == 0 )
{
i++;
j++;
next[i] = j;
}
else if (T[i-1] == T[j-1])//字符串从T[0]开始比较
{
i++;
j++;
next[i] = j;
}
else
{
j = next[j];//前缀和后缀不相同,j=next[j] 。注意:字符串第一个字符对应j=1,比较时都-1。next数组从next[1]开始存。
}
}
}
int strStr(string haystack, string needle) {
if(haystack.length()<needle.length())
return -1;
if(needle == "")
return 0;
int i = 1;//主串下标
int j = 1;//子串下标
int *next = new int[needle.length()+1];
get_next(needle , next);
while(i<=haystack.length() &&j<=needle.length())
{
if(j == 0 || haystack[i-1] ==needle[j-1])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if(j > needle.length())
{
return i-j;
}
else
{
return -1;
}
}