题目描述
给你一个非空模板串S,一个文本串T,问S在T中出现了多少次
方法一:暴力求解
求解思路
对于本题目要求出模板串S在文本串T中出现的次数,我们想到直接从文本串T的第一个位置往后寻找模板串S长度的子串,然后拿出来和S比较即可,并且我们设置res变量来记录相同的个数。
解题代码
class Solution {
public:
int kmp(string S, string T)
{
if(S.empty() || S.size() > T.size()) return 0; // 边界
int hyres = 0, next[S.size() + 1];
next[0] = -1;
for(int pre = -1, cur = 0; cur < S.size();)
{
if(pre == -1 || S[pre] == S[cur])
{ //暴力匹配
pre++;
cur++;
next[cur] = pre;
}
else pre = next[pre];
}
for(int pattern = 0, cur = 0; cur < T.size();)
{ //模板串匹配
if(pattern == -1 || S[pattern] == T[cur])
{
pattern++;
cur++;
if(pattern == S.size())
{ //如果完全匹配
hyres++; // 结果加1
pattern = next[pattern];
}
}
else pattern = next[pattern];
}
return hyres; // 返回结果
}
};复杂度分析
时间复杂度:一层循环加上一遍字符串遍历,因此时间复杂度为,N为循环,M为字符串子串的长度。
空间复杂度:没有引入额外的内存地址空间,因此空间复杂度为
方法二:KMP优化求解
求解思路
对于字符串子串匹配算法,我们使用KMP进行求解,首先构建一个next数组,用next[i]来表示模板串S中最长公共前缀的结束的下标,并且next[0]赋值-1。接着进行匹配,若匹配成功则两个字符串同步前进,若匹配失败则继续往前搜索到next数组中的位置,若为完全匹配,则跳到当前子串起始位置后一个,并更新到next的最后一个匹配值,来重新匹配下一个字符串。
解题代码
class Solution {
public:
int kmp(string S, string T) {
int n = T.length(); // 保存T的长度
int m = S.length(); // 保存S的长度
int hyres = 0;
vector<int> next(m + 1); // 声明next数组
next[0] = -1; // next数组从-1开始
int k = -1;
for(int i = 0; i < m;)
{ //初始化next数组
if(k == -1 || S[k] == S[i])
{
k++;
i++;
next[i] = k;
}
else
k = next[k];
}
k = 0; // 每次next数组从0开始,后面访问都会+1
for(int i = 0; i < n;)
{
if(k == -1 || T[i] == S[k])
{ //若是匹配,k 与 i 一同加
k++;
i++;
if(k == m)
{ //找到一个,将k置为next最大值
hyres++; // 结果加1
k = next[k];
}
}
else //否则继续往前搜索
k = next[k];
}
return hyres; // 返回结果
}
};复杂度分析
时间复杂度:一层循环,因此时间复杂度为
空间复杂度:因为引入next数组,所以空间复杂度为,N为next数组的长度。

京公网安备 11010502036488号