题目描述
给你一个非空模板串S,一个文本串T,问S在T中出现了多少次
示例1
输入 “ababab”,“abababab”
返回值 2
示例2
输入 “abab”,“abacabab”
返回值 1
备注:空间O(n)时间O(n)的算法
一定要看清楚给定的是模式串还是匹配串。在本题题解中使用到的下标均是从 1 开始的。因此需要进行一定的预处理。
KMP算法的难点在于next数组的求解,只与模式串有关,例如next[i] 表示在1~i 长度的模式串中,前缀与后缀相等的最大长度。
给定模式串:abababc
子串 | next数组 | next数组值 | 原因 |
---|---|---|---|
a | next[1] | 0 | 前缀后缀没有 |
ab | next[2] | 0 | 前缀后缀没有 |
aba | next[3] | 1 | 前缀:a后缀:a |
abab | next[4] | 2 | 前缀:ab后缀:ab |
ababa | next[5] | 3 | 前缀:aba后缀:aba |
ababab | next[6] | 4 | 前缀:abab后缀:abab |
abababc | next[7] | 0 | 前缀后缀没有 |
class Solution {
public:
int kmp(string S, string T) {
// write code here
int n=S.size();//模板串
int m=T.size();
int ne[100010];
vector<char> s(n+1);
vector<char> t(m+1);
for(int i=0;i<n;i++) s[i+1]=S[i];
for(int i=0;i<m;i++) t[i+1]=T[i];
//求解next数组
for(int i=2,j=0;i<=n;i++)
{
while(j&&s[i]!=s[j+1]) j=ne[j];//不匹配使用next数组
if(s[i]==s[j+1]) j++;//匹配的话 向下移动
ne[i]=j;
}
int res=0;
//匹配过程
for(int i=1,j=0;i<=m;i++)
{
while(j&&t[i]!=s[j+1]) j=ne[j];
if(t[i]==s[j+1]) j++;
if(j==n)
{
res++;
j=ne[j];//匹配串中可能有多个模式串
}
}
return res;
}
};