首页 > 代码库 > 字符串匹配算法 之 基于DFA(确定性有限自动机)
字符串匹配算法 之 基于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 else180 {181 printf(" ");182 }183 }184 printf("\nEnd Position:%d",end);185 }186 else187 {188 printf("结果出错了!");189 }190 Delete(&array,b);191 return 1;192 }
代码参考:出处
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。