字符串匹配算法 之 基于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 }

代码参考:出处

字符串匹配算法 之 基于DFA(确定性有限自动机)

时间: 2024-10-10 20:42:48

字符串匹配算法 之 基于DFA(确定性有限自动机)的相关文章

4种字符串匹配算法:BS朴素 Rabin-karp 有限自动机 KMP(上)

字符串的匹配的算法一直都是比较基础的算法,我们本科数据结构就学过了严蔚敏的KMP算法.KMP算法应该是最高效的一种算法,但是确实稍微有点难理解.所以打算,开这个博客,一步步的介绍4种匹配的算法.也是<算法导论>上提到的.我会把提到的四种算法全部用c/c++语言实现.提供参考学习.下图的表格,介绍了各个算法的处理时间和匹配时间.希望我写的比较清楚.如果不理解的,或者不对的,欢迎留言. 字符串匹配算法及其处理时间和匹配时间 算法 预处理时间 匹配时间 朴素算法 0 O((n-m+1)m) Rabi

4种字符串匹配算法:BS朴素 Rabin-karp 有限自动机 KMP(中)

接着上文(地址),我们来聊一聊自动机算法(有限自动机字符串匹配算法)和KMP算法. ====#=有限自动机算法=#===== 关于有限自动机,网上的分析的资源,大部分都很笼统,算导上的知识点,全是数学公式,看的也会特别累.因此,打算从算导的第一题开始讲起.从习题入手,讲这个算法的思想. 例子:对模式 P = aabab构造出相应的字符串匹配自动机,并说明它在文本字符串T=aaababaabaababaab上的操作过程. 再讲这个例子之前,我们有必要先来了解一下自动机是什么意思? 有限自动机是什么

字符串匹配算法

字符串匹配问题的形式定义: 文本(Text)是一个长度为 n 的数组 T[1..n]: 模式(Pattern)是一个长度为 m 且 m≤n 的数组 P[1..m]: T 和 P 中的元素都属于有限的字母表 Σ 表: 如果 0≤s≤n-m,并且 T[s+1..s+m] = P[1..m],即对 1≤j≤m,有 T[s+j] = P[j],则说模式 P 在文本 T 中出现且位移为 s,且称 s 是一个有效位移(Valid Shift). 比如上图中,目标是找出所有在文本 T=abcabaabcaba

典型字符串匹配算法实现 - 单字符串匹配算法

博客源址:http://www.jimye.com/dian-xing-zi-fu-chuang-pi-pei-suan-fa-shi-xian/ 提示:要继续向下看 相信大家对快捷键ctrl+F是做什么用的都应该很熟悉了,无论是文本编辑.网页浏览等程序上它都意味着字符串搜索,我们提供一个关键字,它将找到当前页面上的所有该关键字所在的位置.关键字称为模式串,在文本T中寻找模式串P出现的所有出现的位置,解决这种问题的算法叫做字符串匹配算法.字符串匹配算法可以说是计算机科学中最古老.研究最广泛的问题

字符串匹配算法的分析【转】

转自:https://www.cnblogs.com/adinosaur/p/6002978.html 问题描述 字符串匹配问题可以归纳为如下的问题:在长度为n的文本T[1...n]中,查找一个长度为m的模式P[1...m].并且假设T,P中的元素都来自一个有限字母集合?.如果存在位移s,其中0≤s≤n-m,使得T[s+1..s+m] = P[1..m].则可以认为模式P在T中出现过. 1. 朴素算法 最简单的字符串匹配算法是朴素算法.该算法最直观,通过遍历文本T,对每一个可能的位移s都比较T[

多模字符串匹配算法之AC自动机—原理与实现

简介: 本文是博主自身对AC自动机的原理的一些理解和看法,主要以举例的方式讲解,同时又配以相应的图片.代码实现部分也予以明确的注释,希望给大家不一样的感受.AC自动机主要用于多模式字符串的匹配,本质上是KMP算法的树形扩展.这篇文章主要介绍AC自动机的工作原理,并在此基础上用Java代码实现一个简易的AC自动机. 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 应用场景-多模字符串匹配 我们现在考虑这样一个问题,在一个文本串t

时空权衡之输入增强 ----字符串匹配算法Horspool算法和Boyer-Moore算法

在算法设计的时空权衡设计技术中,对问题的部分或者全部输入做预处理,对获得的额外信息进行存储,以加速后面问题的求解的思想,我们称作输入增强. 其中字符串匹配算法Horspool算法和Boyer-Moore算法就是输入增强的例子. 首先了解一下字符串匹配的概念.我们把在一个较长的n个字符的串中,寻找一个给定的m个字符的串的问题,称为字符串匹配问题.较长的串称为text,而需要寻找的串称为pattern. 字符串匹配问题的蛮力算法很好理解:我们把pattern与text第一个字符对齐,从左往右比较pa

字符串匹配算法KMP算法

数据结构中讲到关于字符串匹配算法时,提到朴素匹配算法,和KMP匹配算法. 朴素匹配算法就是简单的一个一个匹配字符,如果遇到不匹配字符那么就在源字符串中迭代下一个位置一个一个的匹配,这样计算起来会有很多多余的不符合的匹配做了冗余的比较.假设源字符串长n,字串长m 该算法最差时间复杂度为 m*(n-m+1),记为O(n*m);这里不做过多解释朴素匹配算法. KMP算法: kmp算法不是在源字符串中下手,他是从字串下手,比如我要在源字符串(acabaabaabcacaabc)中匹配一个字符串字串(ab

【算法设计与分析基础】19、字符串匹配算法

package cn.xf.algorithm.ch07inputEnhancement; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; /** * * 功能:字符串匹配算法,(还有一种叫KMP算法的,也是很经典的算法,就是比较复杂) * * 第一步:对于给定的长度为m的模式和在模式文本中用到的字母表,按照上面的描述构造移动表 * 第二步:将模式与文本的开