KMP算法的过程演示

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值