[數據結構和算法]LZ77壓縮算法三部曲——1.KMP算法(C語言)

KMP算法的理論部分就不在贅述了,有不懂的小夥伴可以參考這個帖子,感覺寫的挺不錯的。從頭到尾徹底理解KMP

個人比較喜歡簡單粗暴的直接上代碼,又看不懂的小夥伴可以下下面評論提出來。

下面的程序是爲了後面的LZ77 壓縮算法做鋪墊的,其實現的是從源數據中找到與匹配數據最長的數據的座標和匹配長度。繞的有點暈哈;
舉個栗子:
字符串s = “a b a c a a b a c a b a c a b a a b b”;
字符串p = “a b a c a b”;
從字符串s中找到與字符串p匹配的數據的下標和最長匹配數據長度;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;

#define TEST_STR	0	//選擇測試對象是字符串還是數組

typedef struct KMP{
	uchar *src; 	//源數據
	uchar *dst;	//要求匹配的數據
	ushort sLen;	//源數據長度
	ushort pLen;	//匹配數據長度
	ushort coord;	//匹配到數據記錄其座標
	ushort matchLen; 	//最大的匹配長度
}KMP_TypeDef;

KMP_TypeDef KMP;

bool KMP_Search(KMP_TypeDef *KMP){
	int i=0,j=0,max=0,baki=0;
	if(KMP->sLen==0 || KMP->pLen==0){
		return false;
	}	
	while(i < KMP->sLen){	//把源數據遍歷一遍
		if(KMP->src[i] == KMP->dst[j]){	//從源數據中找到與匹配數據相同的數據
			i++;
			j++;
			if(j >= max){		
				max = j; 	//更新最長匹配數據長度
				baki = i;	//備份座標值
			}
		}
		else{
			i = i - j + 1;
			j = 0;	//如果失配,則下一次匹配從匹配數據的第一個數據開始
		}
	}
	KMP->coord = baki-max;	//找到最佳匹配數據的下標
	KMP->matchLen = max; 	//匹配數據長度
	return true;
} 

int main(void){
	uchar str[100]={0};
	KMP_TypeDef kmp;
#if TEST_STR	
	kmp.src = "a b a c a a b a c a b a c a b a a b b";//"ABCDEFGHIJKLMNOPQRSTUVWXYZd abcdefghijklmnopqrstuvwxyz  ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdesfghijklmnopqrstuvwxyz";//
	kmp.dst = "a b a c a b";//"abcdesfghiu";//
	kmp.sLen = strlen(kmp.src);
	kmp.pLen = strlen(kmp.dst);
	printf("slen:%d - plen:%d\n",kmp.sLen,kmp.pLen);
#else
	uchar arr1[] = {0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f};
	uchar arr2[] = {0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b};
	kmp.sLen = sizeof(arr1)/sizeof(arr1[0]);
	kmp.pLen = sizeof(arr2)/sizeof(arr2[0]);
	kmp.src = malloc(kmp.sLen * sizeof(arr1[0]));
	kmp.dst = malloc(kmp.pLen * sizeof(arr2[0]));
	memcpy(kmp.src, arr1, kmp.sLen); 
	memcpy(kmp.dst, arr2, kmp.pLen);
	printf("slen:%d - plen:%d\n",kmp.sLen,kmp.pLen);
#endif
	KMP_Search(&kmp);
	printf("coord:%d - Len:%d\n",kmp.coord, kmp.matchLen);		//打印下標和長度
	strncpy(str, kmp.dst, kmp.matchLen);	//字符串拷貝,這裏拷貝數據也沒出錯
	printf("Match: %s\n",str);	//打印字符串,測試數組也將打印成字符串,具體內容可以參照ASCII碼錶
}
測試結果
  1. #define TEST_STR 0
    在這裏插入圖片描述

  2. #define TEST_STR 1
    在這裏插入圖片描述

  3. 把字符串替換一下
    kmp.src ="ABCDEFGHIJKLMNOPQRSTUVWXYZd abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdesfghijklmnopqrstuvwxyz";
    kmp.dst = "abcdesfghiu";
    在這裏插入圖片描述

不知道大家需不需要了解一下LZ77壓縮算法的C語言實現程序,這樣吧。有需要的小夥伴下面評論一下,或者博文瀏覽量超過5W再更新LZ77壓縮算法,不然更新了沒人看也悲哀啊
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章