字符串匹配算法 之 基於DFA(確定性有限自動機)


確定有限自動機定義: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 }

代碼參考:出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM