//优点: KMP算法巧妙的消除了指针的回溯问题,用一个next数组来确定了下一次
// j的匹配位置使得原问题的复杂度由O(mn)下降到了O(m+n)
//思想: 在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i
// 不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i
// 右移1位,并将j置0,继续进行比较。
//匹配实现代码如下:
#include <cstring>
const int N = 101;
int next[N];
int ans = 0;
void getNext( char * p, int * next );
void kmp()
{
int len1 = strlen(s);
int len2 = strlen(p);
int i = 0, j = 0;
while ( i < len1 )
{
if ( j == -1 || s[i] == p[j] )
{
i++;
j++;
}
else
{
j = next[j];
}
if ( j == len2 )
{
ans++;
j = next[j];
}
}
}
//可以看出,KMP算法的关键在于求算next[N]数组的值,即为
//求出模式串(p)每个位置处的最长的后缀与前缀相同的长度
//按照递推的思想来求:
//根据定义next[0] = -1。
//假设有next[j] = k, 即P[0...k-1] == P[j-k,j-1],则:
// 1)若P[j] == P[k],则有P[0..k] == P[j-k,j],很显然,next[j+1] = next[j] + 1 = k + 1;
// 2)若P[j] != P[k],则可以把其看做模式匹配的问题(P串的自匹配问题),
// 即匹配失败的时候,k = next[k]。
//实现代码如下:
void getNext()
{
int j = 0, k = -1;
next[0] = -1;
int len2 = strlen(p);
while ( j < len2 )
{
if ( k == -1 || p[k] == p[j] )
{
k++;
j++;
next[j] = k;
}
else
{
k = next[k];
}
}
}
// j的匹配位置使得原问题的复杂度由O(mn)下降到了O(m+n)
//思想: 在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i
// 不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i
// 右移1位,并将j置0,继续进行比较。
//匹配实现代码如下:
#include <cstring>
const int N = 101;
int next[N];
int ans = 0;
void getNext( char * p, int * next );
void kmp()
{
int len1 = strlen(s);
int len2 = strlen(p);
int i = 0, j = 0;
while ( i < len1 )
{
if ( j == -1 || s[i] == p[j] )
{
i++;
j++;
}
else
{
j = next[j];
}
if ( j == len2 )
{
ans++;
j = next[j];
}
}
}
//可以看出,KMP算法的关键在于求算next[N]数组的值,即为
//求出模式串(p)每个位置处的最长的后缀与前缀相同的长度
//按照递推的思想来求:
//根据定义next[0] = -1。
//假设有next[j] = k, 即P[0...k-1] == P[j-k,j-1],则:
// 1)若P[j] == P[k],则有P[0..k] == P[j-k,j],很显然,next[j+1] = next[j] + 1 = k + 1;
// 2)若P[j] != P[k],则可以把其看做模式匹配的问题(P串的自匹配问题),
// 即匹配失败的时候,k = next[k]。
//实现代码如下:
void getNext()
{
int j = 0, k = -1;
next[0] = -1;
int len2 = strlen(p);
while ( j < len2 )
{
if ( k == -1 || p[k] == p[j] )
{
k++;
j++;
next[j] = k;
}
else
{
k = next[k];
}
}
}