关于KMP算法前缀next最同俗易懂的解释请看:
http://blog.youkuaiyun.com/yearn520/article/details/6729426next数组代码:(将第一位赋值为-1,无重复位置赋值为0,重复位一次递增)
void SetNext()//子串的next数组,如果只看代码的话,很难得出值的确定方法。
{
int i=0,j=-1;
Next[0]=-1;
while(i<M)
{
if(j==-1||b[i]==b[j])//b为模式数组
{
i++; j++;
Next[i]=j;
}
else
j=Next[j];
}
}
- KMP匹配代码:(依赖上面的SetNex()函数)
int Kmp()
{
int i=0,j=0;
SetNext();
while(i<N)//a为目标数组
{
if(j==-1||a[i]==b[j])//这里j=-1的情况就是第一个字符不匹配的情况。
{
i++;j++;
}
else
j=Next[j];//如果匹配不上,这里回溯j,
if(j==M)//如果匹配成功了。
return i-j+1;//回溯j最终的位子。
}
return -1;
}
分析&题解:
很裸的KMP,计算目标字符串中含有多少个子串。修改一下KMP函数,每匹配完成一次,计数++,直到匹配不了为止。AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
int N,M;
char a[1234];
char b[1234];
int Next[1234];
int cnt ;
void SetNext()//子串的next数组,如果只看代码的话,很难得出值的确定方法。
{
int i=0,j=-1;
Next[0]=-1;
while(i<M)
{
if(j== -1||b[i]==b[j])
{
i++; j++;
Next[i]=j;
}
else
j=Next[j];
}
}
void Kmp()
{
int i=0,j=0;
SetNext();
while(i<N)
{
if(j== -1||a[i]==b[j])//这里j=-1的情况就是第一个字符不匹配的情况。
{
i++;j++;
}
else
j=Next[j];//如果匹配不上,这里回溯j,
if(j==M)//如果匹配成功了。
{
j = 0;
cnt++;
}
}
return ;
}
int main()
{
while(scanf("%s", &a) )
{
if(a[0] == '#')
break;
cnt = 0;
scanf("%s", &b);
N = strlen(a);
M = strlen(b);
SetNext();
Kmp();
cout << cnt << endl;
}
}