子串的定位操作被称之为串的模式匹配,即求子串在主串中的位置。
1.暴力匹配算法
首先我们来看不使用KMP算法进行的串的模式匹配。为方便将字符串第一个字符的位序计为1
int Index(string s, string t)
{
int i = 1, j = 1;
while (i <= s.size()&&j <= t.size())
{
if (s[i] == t[j])
{
++i;++j;
}
else
{
i = i - j + 2;j = 1;
}
}
if (j > t.size())
return i - t.size();
else
return 0;
}
这种模式匹配算法最坏的时间复杂度为O(nm),其中n和m分别为主串和模式串的长度。
2.KMP算法
同样的,为方便将字符串第一个字符的位序计为1
int Index_KMP(string s, string t, int next[])
{
int i = 1, j = 1;
while (i < s.size() && j < t.size())
{
if (j == 0 || s[i] == t[j])
{
++i;++j;
}
else
j = next[j];
}
if (j > t.size())
return i - t.size();
else
return 0;
}
时间复杂度为O(n+m)
其中关于next数组的求法个人认为在字符串长度较短的情况下手算远快于写代码。
手算方法:当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]=S的最长相等前后缀长度+1
下面给出next数组的求解代码,不易理解。
void get_next(string t, int next[])
{
int i = 1, j = 0;
next[1] = 0;
while (i < t.size())
{
if (j == 0 || t[i] == t[j])
{
++i;++j;
next[i] = j;
}
else
j = next[j];
}
}