KMP算法的过程演示
`
#include <stdio.h>
#include <string.h>
#include <graphics.h>
#include <windows.h>
#define W 1400
#define H 600
#define BIAN 100
#define GZ 30
#define X(i) (BIAN+GZ*(i*2))
#define Y(i) (BIAN+GZ*i)
#define Arow 1
#define Brow 7
//*******************画图功能区************************************
//画指针和名称
void huazhizhen(int i, int color, int row, char* str, int* n) {
//画指针
setcolor(color);
if (row == Brow + 3 || row == Brow - 1 || row == Arow + 3) { // row = 4 6 10
line(X(i) + (GZ - 2), Y(row) - GZ / 5, X(i) + (GZ - 2), Y(row) - GZ * 4 / 5); //上指针
line(X(i) + (GZ - 2), Y(row) - GZ * 4 / 5, X(i) + (GZ - 2) - 3, Y(row) - GZ / 2);
line(X(i) + (GZ - 2), Y(row) - GZ * 4 / 5, X(i) + (GZ - 2) + 3, Y(row) - GZ / 2);
row = row + 2;
} else {
line(X(i) + (GZ - 2), Y(row) - GZ / 5, X(i) + (GZ - 2), Y(row) - GZ * 4 / 5); //下指针
line(X(i) + (GZ - 2), Y(row) - GZ / 5, X(i) + (GZ - 2) - 3, Y(row) - GZ / 2);
line(X(i) + (GZ - 2), Y(row) - GZ / 5, X(i) + (GZ - 2) + 3, Y(row) - GZ / 2);
}
//合并str 和 n 为 str1
char ai[5];
char str1[12];
strcpy(str1, str);
if (n != NULL) {
sprintf(ai, "%d", *n);
strcat(str1, ai);
}
//输出 str1
xyprintf(X(i) + (GZ - 2 - 3), Y((row - 1)) - GZ * 3 / 5, str1);
Sleep(200);
}
//输出标注符号
void biaozhu_J(int i, int color, int row, char* str) {
setcolor(color);
outtextxy(X(i) - 10 + (GZ - 2 - 3), Y((row + 2)) - GZ * 4 / 5, str);
Sleep(20);
}
//输出对比后有颜色的字符
void drawCharArray1(char *A, char *B, int row, int ii, int B_go) {
int AA = strlen(A);
int B_row = row + 1;
char C[AA] = {0};
//把数组B转成数组C 数组C随着B_go变化下标位置
for (int i = 0; i < AA; i++) {
if (B[i]) {
C[B_go + i] = B[i];
}
}
//输出数组A和数组C
if (A[ii] == C[ii] && ii >= B_go) {//A 和 C 相同 且>B_go 就按 绿色 输出字符
setcolor(GREEN);
outtextxy(X(ii) + (GZ - 5), Y(row) + GZ / 5, A[ii]);
outtextxy(X(ii) + (GZ - 5), Y(B_row) + GZ / 5, C[ii]);
} else if (A[ii] != C[ii] && ii >= B_go && C[ii] != 0) { //A 和 C 不同 且>B_go C不为空 就按 上绿下红 输出字符
setcolor(GREEN);
outtextxy(X(ii) + (GZ - 5), Y(row) + GZ / 5, A[ii]);
setcolor(RED);
outtextxy(X(ii) + (GZ - 5), Y(B_row) + GZ / 5, C[ii]);
}
Sleep(300);
}
//只画白色的 A[] B[] 字符
void drawCharArray_white(char *A, char *B, int row, char* strA, char* strB, int B_go) {
int AA = strlen(A);
int B_row = row + 1;
//把B[]转成C[]
char C[AA] = {0};
for (int i = 0; i < AA; i++) {
if (B[i]) {
C[B_go + i] = B[i];
}
}
setcolor(WHITE);
//输出数组名
outtextxy(X(0) - (GZ - 2), Y(row) + GZ / 5, strA);
outtextxy(X(0) - (GZ - 2), Y(B_row) + GZ / 5, strB);
Sleep(20);
//输出数组内容
for (int i = 0; i < AA; i++) {
outtextxy(X(i) + (GZ - 5), Y(row) + GZ / 5, A[i]);
outtextxy(X(i) + (GZ - 5), Y(B_row) + GZ / 5, C[i]);
Sleep(20);
}
}
//黑掉字符,相当于清除字符数组B[]
void drawBlackArray(char *A, int row,int go) {
int AA = strlen(A);
for (int i = 0; i < AA+go; i++) {
setcolor(BLACK);
outtextxy(X(i) + (GZ - 5), Y(row) + GZ / 5, "██");
}
}
//给初始化next[]用
void drawCharArray_Next(char *A, int row, char* str, int ii, int jj) {
int AA = strlen(A);
setcolor(WHITE);
outtextxy(X(0) - (GZ - 2), Y(row) + GZ / 5, str);
Sleep(30);
for (int i = 0; i < AA; i++) {
if (ii == i) {
setcolor(GREEN);
} else if (jj == i) {
setcolor(RED);
} else {
setcolor(WHITE);
}
outtextxy(X(i) + (GZ - 5), Y(row) + GZ / 5, A[i]);
Sleep(30);
}
}
void drawInitNext(int *A, int num, int row) {
char str_next[] = "next[1]:";
// 黑掉之前的“next[num]”
setcolor(BLACK);
char ai[5];
strcpy(str_next, "next[");
sprintf(ai, "%d", num - 1);
strcat(str_next, ai);
strcat(str_next, "]:");
outtextxy(X(0) - (GZ) * 5 / 2, Y(row) + GZ / 5, str_next);
// 重写“next[num]”
setcolor(WHITE);
strcpy(str_next, "next[");
sprintf(ai, "%d", num);
strcat(str_next, ai);
strcat(str_next, "]:");
outtextxy(X(0) - (GZ) * 5 / 2, Y(row) + GZ / 5, str_next);
//再写出next[num]的各值
for (int i = 0; i < num; i++) {
setcolor(RED);
xyprintf(X(i) + (GZ - 2), Y(row) + GZ / 5, "%d", A[i]);
}
Sleep(20);
}
//***********************************************************************
//调用了普通求next的方式,这里并未直接对next[1]赋值1,但通过函数第一次运行,也可以得出它的值为1
void Next(char* B, int *next) {
char str_B[] = "B:"; // 定义添加字符串 名称字符 B:
char biaozhu_kuohao[] = "[ ]";
char biaozhu_dengyu[] = "= ";
char B_i_pre[] = "B[i-1]";
char B_j_pre[] = "B[j-1]";
char Bi_Bj_Y[] = "B[j-1]==B[i-1]";
char Bi_Bj_N[] = "B[j-1]!=B[i-1]";
char next_j[] = "4:j= next[j]";
char str_next_1[] = "3:next[]=";
char str_i_1[] = "1:i++";
char str_j_1[] = "2:j++";
char str_i[] = "i= ";
char str_j[] = "j= ";
// 画字符数组B[]
next[1] = 0;
int i = 1;
int j = 0;
int B_len = strlen(B);
drawCharArray_Next(B, Brow, str_B, i, j);
while (i < B_len) {
//------------------画图标记---------------------
drawInitNext(next + 1, i, Brow + 1); // 画next[] 数组
if (j == 0) {
huazhizhen(j, YELLOW, Brow, str_j, &j); //"j=0"
huazhizhen(j, BLACK, Brow, str_j, &j);
huazhizhen(i, YELLOW, Brow, str_i, &i); //“i=1”
huazhizhen(i, BLACK, Brow, str_i, &i);
} else {
huazhizhen(i - 1, YELLOW, Brow, B_i_pre, NULL);
biaozhu_J(i - 1, YELLOW, Brow - 1, biaozhu_kuohao);
huazhizhen(j - 1, YELLOW, Brow, B_j_pre, NULL);
biaozhu_J(j - 1, YELLOW, Brow - 1, biaozhu_kuohao);
huazhizhen(j - 1, BLACK, Brow, B_j_pre, NULL);
huazhizhen(i - 1, BLACK, Brow, B_i_pre, NULL);
}
//-----------------------------------------------------------
int pre_i=i;
int pre_j=j;
if (j == 0 || B[i - 1] == B[j - 1]) {
//------------------画图标记---------------------
if (B[i - 1] == B[j - 1]) {
huazhizhen(j - 1, RED, Brow, Bi_Bj_Y, NULL);
huazhizhen(j - 1, BLACK, Brow, Bi_Bj_Y, NULL);
Sleep(30);
}
//------------------------------------------------
i++;
j++;
//------------------画图标记---------------------
huazhizhen(i, RED, Brow, str_i_1, NULL);
huazhizhen(j, RED, Brow, str_j_1, NULL);
drawCharArray_Next(B, Brow, str_B, i, j);
//------------------------------------------------
next[i] = j;
//------------------画图标记---------------------
huazhizhen(i - 1, RED, Brow + 3, str_next_1, &j);
huazhizhen(j, BLACK, Brow, str_j_1, NULL);
huazhizhen(j, YELLOW, Brow, str_j, &j); //"j=0"
drawInitNext(next + 1, i, Brow + 1);
huazhizhen(j, BLACK, Brow, str_j, &j);
huazhizhen(i - 1, BLACK, Brow + 3, str_next_1, &j);
huazhizhen(i, BLACK, Brow, str_i_1, NULL);
//--------------------------------------------------
} else {
//------------------画图标记---------------------
huazhizhen(j - 1, RED, Brow, Bi_Bj_N, NULL);
huazhizhen(j - 1, BLACK, Brow, Bi_Bj_N, NULL);
huazhizhen(j, YELLOW, Brow, next_j, NULL);
biaozhu_J(next[j], YELLOW, Brow, biaozhu_dengyu);
huazhizhen(j, BLACK, Brow, next_j, NULL);
int a = j;
//-------------------------------------------------
j = next[j];
//------------------画图标记---------------------
huazhizhen(j, YELLOW, Brow, str_j, &j);
drawCharArray_Next(B, Brow, str_B, i, j);
biaozhu_J(next[a], BLACK, Brow, biaozhu_dengyu);
huazhizhen(j, BLACK, Brow, str_j, &j);
//------------------------------------------------
}
biaozhu_J(pre_i - 1, BLACK, Brow - 1, biaozhu_kuohao);
biaozhu_J(pre_j - 1, BLACK, Brow - 1, biaozhu_kuohao);
}
}
//KMP 的算法
int KMP(char* A, char* B) {
char str_A[] = "A:";
char str_B[] = "B:";
char str_i[] = "i";
char str_j[] = "j";
drawCharArray_white(A, B, Arow, str_A, str_B, 0);
Sleep(200);
int next[10];
Next(B, next); //根据模式串B,初始化next数组
int i = 1;
int j = 1;
int AA = strlen(A);
int BB = strlen(B);
int pre_j = 1;
int go_j = 0;
while (i <= AA && j <= BB) {
//j==0:代表模式串的第一个字符就和当前测试的字符不相等;
//S[i-1]==T[j-1];如果对应位置的字符相等,两种情况下,指向当前测试的两个指针下标i和j都向后移
if (j == 0 || A[i - 1] == B[j - 1]) {
huazhizhen(i - 1, YELLOW, Arow, str_i, NULL);
huazhizhen(j+go_j-1, RED, Arow + 3, str_j, NULL);
drawCharArray1(A, B, Arow, i - 1, go_j);
Sleep(20);
huazhizhen(i - 1, BLACK, Arow, str_i, NULL);
huazhizhen(j+go_j-1, BLACK, Arow + 3, str_j, NULL);
i++;
j++;
pre_j = j;
} else {
j = next[j]; //如果测试的两个字符不相等,i不动,j变为当前测试字符串的next值
huazhizhen(i - 1, YELLOW, Arow, str_i, NULL);
huazhizhen(pre_j +go_j-1, RED, Arow + 3, str_j, NULL);
drawCharArray1(A, B, Arow, i - 1, go_j);
Sleep(20);
go_j = go_j + (pre_j - j);
drawBlackArray(B,Arow+1,go_j);
drawCharArray_white(A, B, Arow,str_A, str_B, go_j);
Sleep(20);
huazhizhen(i - 1, BLACK, Arow, str_i, NULL);
huazhizhen(j + go_j - 1, BLACK, Arow + 3, str_j, NULL);
pre_j = j;
}
Sleep(500);
}
if (j > BB) { //如果条件为真,说明匹配成功
return i - BB;
}
return -1;
}
int main() {
char A[21] = "ABCABABCDABABDABABCA";
char B[21] = "ABABCA";
// init_console();
initgraph(W, H); //开窗口
setbkmode(TRANSPARENT);
setbkcolor(BLACK);
int i = KMP(A, B);
printf("%d\n", i);
getchar();
closegraph();
return 0;
}