示例:
目标串:123abc456abc789abc
模式串: abc
输入:3 9 15
大致思路:
首先通过KMP算法判断目标串中是否含有模式串,如果不含有的话,不用进行后面的判断,直接输出-1
若含有模式串,则需要将模式串出现的所有位置输出。方法是通过截取字符串,相当于将在目标串中已经判断过的位置剪去,例如目标串:123abc456abc789abc 模式串: abc,第一次匹配出现位置为3,tmp=456abc789abc,然后将tmp作为目标串接着匹配,知道目标串中没有模式串或者目标串的长度小于模式串。
代码实现
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int kmp(string s, string p, int next[])
{
int s_len = s.size();
int p_len = p.size();
int i = 0, j = 0;
while (i < p_len && j < s_len)
{
if (p[i] == s[j])
{
i++;
j++;
}
else
{
if (i == 0)
j++;
else
i = next[i - 1] + 1;
}
}
if (i < p_len)
return -1;
return j - p_len;
}
void getnext(string p, int next[])
{
int len = p.size();
next[0] = -1;
int i, j;
for (j = 1; j < len; j++)
{
i = next[j - 1];
while (p[j] != p[i + 1] && i >= 0)
i = next[i];
if (p[j] == p[i + 1])
next[j] = i + 1;
else
next[j] = -1;
}
}
int main()
{
string pMain;
string pPattern;
cout << "请输入目标串:" << endl;
cin >> pMain;
cout << "请输入模式串:" << endl;
cin >> pPattern;
vector<int> ans;
int* next = new int[pPattern.size()];
getnext(pPattern, next);
if (kmp(pMain, pPattern, next) == -1)
{
cout << kmp(pMain, pPattern, next);
}
else
{
ans.push_back(kmp(pMain, pPattern, next));
string ppmain = pMain;
while (true)
{
string tmp = "";
for (int i = ans[ans.size() - 1] + pPattern.size(); i < ppmain.size(); i++)
{
tmp += ppmain[i];
}
if (tmp.size() < pPattern.size())
break;
int answer = kmp(tmp, pPattern, next);
if (answer == -1)
break;
else
{
answer += ans[ans.size() - 1];
answer += +pPattern.size();
ans.push_back(answer);
}
}
}
for (int i = 0; i < ans.size(); i++)
{
if (i != 0)
cout << "\t";
cout << ans[i];
}
return 0;
}