確定有限自動機定義:http://en.wikipedia.org/wiki/Deterministic_finite_automaton
自動機在字符串匹配中的應用
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define ALPHABETLENGTH 53 5 #define GETMIN(x,y) ((x)<=(y)?(x):(y)) 6 7 //判定pattern的前k個字符是不是(pattern的前q個字符加上字符a組成的)字符串的后綴 8 int IsSuffix(char *pattern,int k,int q,char a); 9 //創建自動機(二維數組),並且根據給定的pattern完成自動機的初始化 10 void Create(int*** array,char *pattern); 11 //根據創建的自動機進行模式匹配,並返回模式在給定文本中第一次出現的結束位置 12 int DFAMatcher(char* T,int** array,char *pattern); 13 //在程序結束時,將創建的自動機(二維數組)進行銷毀 14 void Delete(int*** array,char *pattern); 15 //一個小函數,用來查找給定的字符a在預先設定的字母表中的位置 16 int SearchChar(char a); 17 //預先設定的字母表,包括26個大小寫的字母以及一個空格,共53個字符 18 char alphabet[ALPHABETLENGTH]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "; 19 20 /* 21 *通過函數來進行二維數組的分配,需要用到三重指針,傳進去的是一個指針數組的地址, 22 *直接傳指針數組的話會造成懸垂指針,數組的構建需要根據pattern來構建 23 *二維數組實際上就相當於自動機(DFA)了 24 */ 25 void Create(int*** array,char *pattern) 26 { 27 //臨時變量 28 int i,j,k; 29 //pattern的長度 30 int patternlength=strlen(pattern); 31 //二位數組的行數等於pattern中字符數加1 32 int x=strlen(pattern)+1; 33 //二維數組的列數等於字母表中所有的字符個數,這里我采用的是26個小寫字母加上26個大寫字母 34 int y=ALPHABETLENGTH; 35 //開始分配二維數組的空間,如果分配失敗的話則要撤銷已分配的單元。這里分兩種情況, 36 //一種是一開始就沒有空間可分配,另一種是分配了一部分以后空間不足。 37 *array=(int**)malloc(sizeof(int)*x); 38 if(NULL==array) 39 { 40 fprintf(stderr,"\nspace is not enough!\n"); 41 return; 42 } 43 for(i=0; i<x; i++) 44 { 45 if(((*array)[i]=(int*)malloc(sizeof(int)*y))==NULL) 46 { 47 while(--i>=0) 48 { 49 free((*array)[i]); 50 } 51 free(*array); 52 fprintf(stderr,"\nspace is not enough!\n"); 53 return; 54 } 55 } 56 //下面開始初始化二維數組的自動機表了 57 for(i=0; i<=patternlength; i++) 58 { 59 for(j=0; j<ALPHABETLENGTH; j++) 60 { 61 k=GETMIN(patternlength+1,i+2); 62 do 63 { 64 --k; 65 66 } 67 while(k>0 && !IsSuffix(pattern,k,i,alphabet[j])); 68 (*array)[i][j]=k; 69 } 70 } 71 for(i=0; i<patternlength+1; i++) 72 { 73 for(j=0; j<ALPHABETLENGTH; j++) 74 { 75 printf("%d ",(*array)[i][j]); 76 } 77 printf("\n"); 78 } 79 } 80 81 //為了實現Pk是Pqa的后綴,k和q是字符數組P的下標表示數組P的前k和前q個字符,a是一個字符表示連接在字符串Pq后面 82 int IsSuffix(char *pattern,int k,int q,char a) 83 { 84 int cmp; 85 char Q[q+1]; 86 Q[q]=a; 87 strncpy(Q,pattern,q); 88 cmp=strncmp(pattern,Q+q-(k-1),k); 89 if(cmp==0) 90 { 91 return 1; 92 } 93 else 94 { 95 return 0; 96 } 97 } 98 99 //查找字符變量a在字母表中的位置 100 int SearchChar(char a) 101 { 102 int i=0; 103 while(alphabet[i]!=a) 104 { 105 ++i; 106 } 107 if(i>(ALPHABETLENGTH-1)) 108 { 109 i=-1; 110 } 111 return i; 112 } 113 //利用自動機進行匹配 114 int DFAMatcher(char* T,int** array,char *pattern) 115 { 116 int i; 117 int n=strlen(T); 118 int m=strlen(pattern); 119 int q=0; 120 int position=0; 121 122 for(i=0; i<n; i++) 123 { 124 position=SearchChar(T[i]); 125 if(position<0) 126 { 127 fprintf(stderr,"字符[%c]不存在\n",T[i]); 128 return -1; 129 } 130 q=array[q][position]; 131 if(q==m) 132 { 133 printf("find!\n"); 134 break; 135 } 136 } 137 if(q!=m) 138 { 139 printf("unfind\n"); 140 i=-1; 141 } 142 return i;//如果匹配成功返回pattern在字符串的結束位置,否則返回-1; 143 } 144 //程序結束進行銷毀二維數組 145 void Delete(int*** array,char *pattern) 146 { 147 int i; 148 int m=strlen(pattern); 149 for(i=m; i>=0; i--) 150 { 151 free((*array)[i]); 152 } 153 free((*array)); 154 } 155 156 int main(void) 157 { 158 char a[100]="defabcababacaghijkl"; 159 char b[10]="ababaca"; 160 int **array; 161 int i; 162 printf("開始構建自動機:\n"); 163 Create(&array,b); 164 printf("自動機構建完畢!\n"); 165 int end=DFAMatcher(a,array,b); 166 int first=end-strlen(b)+1; 167 if(end>=0) 168 { 169 printf("輸入字符串:%s\n",a); 170 printf("模式:%s\n",b); 171 printf("結果:\n"); 172 printf("%s\n",a); 173 for(i=0; i<strlen(a); i++) 174 { 175 if(i==end || i==first) 176 { 177 printf("|"); 178 } 179 else 180 { 181 printf(" "); 182 } 183 } 184 printf("\nEnd Position:%d",end); 185 } 186 else 187 { 188 printf("結果出錯了!"); 189 } 190 Delete(&array,b); 191 return 1; 192 }
代碼參考:出處