#include<stdio.h>
#define MaxSize 1000
#define N 1000
#define OK 1
#define ERROR 0
typedef int Status;
typedef unsigned char SString[MaxSize + 1];//S[0]存串长度
int Index_KMP(SString S,SString T);
void get_next(SString T);
int Longest(SString T, int m);
Status StrAssign(SString S, char *chars);
void StrPrint(SString S);
int next[N];
int main(void)
{
char str1[N] = “aaabaaaab”;
char str2[N] = “aaaab”;
SString T,S;
printf(“主串S为:”);
StrAssign(S,str1);
StrPrint(S);
printf("主串T为:");
StrAssign(T,str2);
StrPrint(T);
int pos = Index_KMP(S,T);
if(pos)
printf("\n主串和子串在第%d个字符处首次匹配\n",pos);
else
printf("\n主串和子串匹配不成功\n");
return 0;
}
int Index_KMP(SString S,SString T)
{
get_next(T);
printf(“next函数为:”);
for(int s = 1; s <= T[0]; s++)
printf("%d",next[s]);
printf("\n");
int i = 1,j = 1;
while(i <= S[0] && j <= T[0])
{
if(j == 0 || S[i] == T[j]) //当T数组回溯到第一个或者子串主串元素相等,都向后移一个位置
{
i++;
j++;
}
else //元素不想等,利用next数组回溯
j = next[j];
if(j > T[0]) //子串从头遍历完毕,在主主串中找到完整子串,返回在S中位置
return i - T[0];
}
return 0;//S主串循环完毕,子串没有匹配完毕,没有找到完整子串出现位置
}
void get_next(SString T)
{
next[1] = 0;
int i;
for(i = 2; i <= T[0]; i++)
{
next[i] = Longest(T,i-1) + 1;
//next数组,存入当前位置的前i-1个数的最大相等前后缀,并加一表示下个要移到位置
}
}
int Longest(SString T, int m)//返回一串字符串的最大相等前后缀个数
{
int n,i,j;
for(n = m -1 ; n >=1; n–) //从当前字符串长度-1开始遍历,直到为1
{
for(i = 1,j = m-n+1; i <= n && j <= m; i++,j++) //判断前缀后缀每个元素是否相等
{
if(T[i] != T[j])
break;
}
if( i > n && j > m)//前后缀每个元素都相等,最大相等前后缀个数找到
return n;
}
return 0;//无相等前后缀,返回个数为0
}
Status StrAssign(SString S, char chars)
{
char c;
int len;
for(len = 0,c = chars; *c; ++len, ++c); //求常量字符串长
if(len > MaxSize)
return ERROR;
else
{
S[0] = len;
for(int i = 1; i <= len; i++,chars++)
S[i] = *chars;
return OK;
}
}
void StrPrint(SString S)
{
for(int i = 1; i <= S[0]; i++)
printf("%c",S[i]);
printf("\n");
}