#include <iostream>
using namespace std;
#define STR_SIZE 1024
#define PAR_SIZE 128
char str[STR_SIZE] = {"abaababaddecab"};
char par[PAR_SIZE] = {"abaabcaba"};
void printarray(int *a, int size);
int cal_k2(char *par, int *par_next, int k2, int j);
void cal_next(char *par, int *par_next, int par_len);
int kmp(char *str, char *par);
void printstep(char *str, char *par, int i, int j);
int main()
{
int ret;
ret = kmp(str, par);
// int sz = 3;
// int *p = new int(sz);
// *(p+1) = 3;
// cout<<*(p+1)<<endl;
//
// printarray(p, sz);
if (ret <0)
{
cout<<"Mismatch!"<<endl;
}
else
{
cout<<"Match:"<<ret<<endl;
}
return 0;
}
void cal_next(char *par, int *par_next , int par_len)
{
par_next[0] = -1;
for (int i=1; i<par_len; i++)
{
int k = par_next[i-1];
if (k==-1 )
{
par_next[i] = k+1;
}
else if(par[i-1] == par[k]) //计算第i个失配的时候
{
par_next[i] = k+1;
}
else
{
k = cal_k2(par, par_next, par_next[k], i-1);
par_next[i] = k + 1;
}
cout<<i<<" ";
}
}
int cal_k2(char *par, int *par_next, int k2, int j)
{
int ret;
if (k2 = -1)
{
return -1;
}
if (par[j]== par[k2])
{
ret = k2;
}
else
{
ret = cal_k2(par, par_next, par_next[k2], j);
}
return ret;
}
int kmp(char *str, char *par)
{
if (!str || !par)
{
return -1;
}
int *par_next;
int str_len, par_len;
str_len = strlen(str);
par_len = strlen(par);
if (str_len==0 || par_len==0 || par_len> str_len)
{
return -1;
}
par_next = new int[par_len];
if (!par_next)
{
return -1;
}
cal_next(par, par_next,par_len);
cout<<"ParNext:"<<endl;
printarray(par_next, par_len);
int i=0,j=0;
bool flag=false;
while(i< str_len)
{
printstep(str, par, i, j);
if (str[i] == par[j])
{
if (j==par_len-1)
{
flag = true;
break;
}
j++;
i++;
}
else //i位置失配
{
if (par_next[j] ==-1)
{
i++;
}
else
{
j = par_next[j];
}
}
}
delete[] par_next;
par_next = NULL;
return flag? i-par_len +1 : -1;
}
void printarray(int *a, int size)
{
if (!a)
{
return;
}
for (int i=0; i<size; i++)
{
cout<<*(a+i)<<" ";
}
cout<<endl;
}
void printstep(char *str, char *par, int i, int j)
{
if (!str || !par)
{
return;
}
for (int k=0;k<i ; k++)
{
cout<<" ";
}
cout<<"↓"<<endl;
cout<<str<<endl;
for (k=0;k<i-j ; k++)
{
cout<<" ";
}
cout<<par<<endl;
cout<<endl;
}