資料結構-字串匹配(KMP演算法、BF演算法、BM演算法)
阿新 • • 發佈:2019-02-04
本程式碼中用了KMP演算法、BF演算法、BM演算法三種演算法進行字串匹配。
文字串儲存在了test.txt中,模式串需自行輸入。
程式碼如下:
#include"stdio.h" #include"stdio.h" #include"stdlib.h" #include"conio.h" #define ASIZE 256 #define XSIZE 200 typedef struct{ char *ch; int length; }HString; //BF演算法 void BF(HString S,HString T) { int i=0,j=0; loop: j=-1; while(i<S.length&&j<T.length) { if(S.ch[i]==T.ch[j]) {i++;j++; } else { i=i-j+1; j=0;} } if(j==T.length) { printf("在位置%d發現匹配!\n",i-j+1);goto loop; } } //KMP演算法 void KMP(HString S,HString T,int *next) { int i=0,j=0; loop: while(i<S.length&&j<T.length) { if(j==-1||S.ch[i]==T.ch[j]) { ++i; ++j; } else j=next[j]; } if(j==T.length) { printf("在位置%d發現匹配!\n",i-j+1); j=-1; goto loop; } } void Next(HString T,int *next) //求next函式 { int i,j=0,k=-1; next[0]=-1; while(j<T.length) { if(k==-1||T.ch[j]==T.ch[k]) { if(T.ch[++j]==T.ch[++k]) next[j]=next[k]; else next[++j]=++k; } else k=next[k]; } } //BM演算法 (Boyer-Moore) 好字尾相關函式 void preBmBc(HString Q, int m, int bmBc[]) { int i; for (i = 0; i <256; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[Q.ch[i]] = m - i - 1; } void suffixes(HString Q, int m, int *suff) { int f, g, i; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && Q.ch[g] == Q.ch[g + m - 1 - f]) --g; suff[i] = f - g; } } } void preBmGs(HString Q, int m, int bmGs[]) { int i, j, suff[Q.length]; suffixes(Q, m, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= 0; --i) if (suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; } int MAX(int i,int j) //求最大值 { if(i>j) return i; else return j; } void BM(HString Q, int m, HString S, int n) { int i, j, bmGs[Q.length], bmBc[256]; preBmGs(Q, m, bmGs); preBmBc(Q, m, bmBc); j = 0; while (j <= n - m) { for (i = m - 1; i >= 0 && Q.ch[i] == S.ch[i + j]; --i); if (i < 0) { printf("在位置%d發現匹配!\n",j+1); j += bmGs[0]; } else j += MAX(bmGs[i], bmBc[S.ch[i + j]] - m + 1 + i); } } int main() { HString S,Q; FILE *fp; if(!(fp = fopen("test.txt" , "r"))) printf("讀取失敗!!\n"); fseek(fp,0,SEEK_END); //檢視檔案大小 int file_size; file_size=ftell(fp); int count=0; //數出換行符數目 char ch; fseek(fp,0,SEEK_SET); printf("檔案中的內容如下:\n"); while((ch=fgetc(fp))!=EOF) { if(ch=='\n') count++; putchar(ch); } file_size-=count; int i=0; //將檔案中的字元寫入S.ch fseek(fp,0,SEEK_SET); S.ch =(char *)malloc(file_size * sizeof(char)); while((ch=fgetc(fp))!=EOF) if(ch!='\n') {S.ch[i]=ch;i++;} S.ch[i]='\0'; S.length=file_size+1; printf("\n請輸入模式串:\n"); Q.ch =(char *)malloc(XSIZE* sizeof(char)); Q.length=0; ch=getchar(); if(ch!='\n') Q.ch[Q.length++]=ch; while(ch!='\n') { ch=getchar(); Q.ch[Q.length++]=ch; } Q.ch[Q.length]='\0'; Q.length--; int *next; //定義next陣列,KMP中使用 next=(int *)malloc(Q.length*sizeof(int)); printf("---------------- BF演算法 ------------------\n"); BF(S,Q); //BF演算法 printf("\n---------------- KMP演算法 ----------------\n"); Next(Q,next); //KMP演算法 KMP(S,Q,next); printf("\n---------------- BM演算法 ------------------\n"); BM(Q,Q.length,S,S.length); //BM 演算法 return 0; }
執行結果如下: