经典的KMP算法,但是本人由于这周一直在乱忙,美来的及提交上,其实还是理解了好久这道提目题目详见hiho第三周。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Solution{
public:
int kmp(const string &patternStr,const string &sourceStr){
int patternSize=patternStr.size();
vector <int> next(patternSize+1,0);
calculateNext(patternStr,next);
/***************
cout<<" ";
for(int i=0;i<patternSize;i++){
cout<<patternStr[i]<<" ";
}
cout<<endl;
for(int i=0;i<=patternSize;i++){
cout<<next[i]<<" ";
}
cout<<endl;
****************/
int sourceSize=sourceStr.size();
int q=-1;//pattern串的已匹配位置
int result=0;
for(int i=0;i<sourceSize;i++){
while(sourceStr[i]!=patternStr[q+1]){
if(q==-1){
break;
}
q=next[q];
}
//当前位置匹配成功模式串对齐点+1
if(sourceStr[i]==patternStr[q+1]){
q++;
}
//完成一次匹配
if(q==patternSize-1){
result++;
//从当前匹配成功的源串起始位置继续下一次匹配
i=i-q+1;
q=-1;
}
}
return result;
}
void calculateNext(const string &pattern,vector <int> &next){
next[0]=-1;
next[1]=-1;
int q=-1;//q表示模式串当前的匹配位置
//i表示当前源串匹配位置
//pattern[q+1]和pattern[i-1]分别代表前缀和后缀需要对齐的位置
for(int i=2;i<=pattern.size();i++){
while(pattern[i-1]!=pattern[q+1]){
if(q==-1){
break;
}
q=next[q];
}
if(pattern[i-1]==pattern[q+1]){
q++;
}
next[i]=q;
}
}
};
int main(){
Solution ss;
//ss.kmp("bacbacbbcabac","");
int n=0;
cin>>n;
string patternStr;
string sourceStr;
for(int i=0;i<n;i++){
cin>>patternStr;
cin>>sourceStr;
cout<<ss.kmp(patternStr,sourceStr)<<endl;
}
return 0;
}
前面的算法整体上来看是O(n2),但是在网上查KMP算法的时间复杂度应该是O(n),看了别人的码才知道自己还是没有真正理解KMP算法的精髓,记得在Baidu知道上一个大牛说KMP的本质是保证在匹配过程中源串不存在回溯操作,
再加上之前自己的理解:根据模式串的纯前缀和纯后缀的最长公共子串的中间结果进行匹配,代码如下,这是别人的代码,最近越来越觉得学会看别人的代码才是真正的成长:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int main()
{
char t[10050],s[1000007];
int c;scanf("%d",&c);
while(c--)
{
scanf("%s%s",t,s);
int flink[10004]={};
int i=0,j=-1;
flink[0]=-1;
int len=strlen(t);
while(i<len)
{
if(j==-1 || t[i]==t[j])
flink[++i]=++j;
else
j=flink[j];
}
int ans=0;
i=j=0;
int n=len;
len=strlen(s);
while(i<len)
{
if(j==-1 || s[i]==t[j])
{
++i;++j;
}
else
{
j=flink[j];
}
if(j==n) ans++;
}
printf("%d\n",ans);
}
return 0;
}