确定有限自动机定义:http://en.wikipedia.org/wiki/Deterministic_finite_automaton

自动机在字符串匹配中的应用

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ALPHABETLENGTH 53
#define GETMIN(x,y) ((x)<=(y)?(x):(y)) //判定pattern的前k个字符是不是(pattern的前q个字符加上字符a组成的)字符串的后缀
int IsSuffix(char *pattern,int k,int q,char a);
//创建自动机(二维数组),并且根据给定的pattern完成自动机的初始化
void Create(int*** array,char *pattern);
//根据创建的自动机进行模式匹配,并返回模式在给定文本中第一次出现的结束位置
int DFAMatcher(char* T,int** array,char *pattern);
//在程序结束时,将创建的自动机(二维数组)进行销毁
void Delete(int*** array,char *pattern);
//一个小函数,用来查找给定的字符a在预先设定的字母表中的位置
int SearchChar(char a);
//预先设定的字母表,包括26个大小写的字母以及一个空格,共53个字符
char alphabet[ALPHABETLENGTH]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "; /*
*通过函数来进行二维数组的分配,需要用到三重指针,传进去的是一个指针数组的地址,
*直接传指针数组的话会造成悬垂指针,数组的构建需要根据pattern来构建
*二维数组实际上就相当于自动机(DFA)了
*/
void Create(int*** array,char *pattern)
{
//临时变量
int i,j,k;
//pattern的长度
int patternlength=strlen(pattern);
//二位数组的行数等于pattern中字符数加1
int x=strlen(pattern)+;
//二维数组的列数等于字母表中所有的字符个数,这里我采用的是26个小写字母加上26个大写字母
int y=ALPHABETLENGTH;
//开始分配二维数组的空间,如果分配失败的话则要撤销已分配的单元。这里分两种情况,
//一种是一开始就没有空间可分配,另一种是分配了一部分以后空间不足。
*array=(int**)malloc(sizeof(int)*x);
if(NULL==array)
{
fprintf(stderr,"\nspace is not enough!\n");
return;
}
for(i=; i<x; i++)
{
if(((*array)[i]=(int*)malloc(sizeof(int)*y))==NULL)
{
while(--i>=)
{
free((*array)[i]);
}
free(*array);
fprintf(stderr,"\nspace is not enough!\n");
return;
}
}
//下面开始初始化二维数组的自动机表了
for(i=; i<=patternlength; i++)
{
for(j=; j<ALPHABETLENGTH; j++)
{
k=GETMIN(patternlength+,i+);
do
{
--k; }
while(k> && !IsSuffix(pattern,k,i,alphabet[j]));
(*array)[i][j]=k;
}
}
for(i=; i<patternlength+; i++)
{
for(j=; j<ALPHABETLENGTH; j++)
{
printf("%d ",(*array)[i][j]);
}
printf("\n");
}
} //为了实现Pk是Pqa的后缀,k和q是字符数组P的下标表示数组P的前k和前q个字符,a是一个字符表示连接在字符串Pq后面
int IsSuffix(char *pattern,int k,int q,char a)
{
int cmp;
char Q[q+];
Q[q]=a;
strncpy(Q,pattern,q);
cmp=strncmp(pattern,Q+q-(k-),k);
if(cmp==)
{
return ;
}
else
{
return ;
}
} //查找字符变量a在字母表中的位置
int SearchChar(char a)
{
int i=;
while(alphabet[i]!=a)
{
++i;
}
if(i>(ALPHABETLENGTH-))
{
i=-;
}
return i;
}
//利用自动机进行匹配
int DFAMatcher(char* T,int** array,char *pattern)
{
int i;
int n=strlen(T);
int m=strlen(pattern);
int q=;
int position=; for(i=; i<n; i++)
{
position=SearchChar(T[i]);
if(position<)
{
fprintf(stderr,"字符[%c]不存在\n",T[i]);
return -;
}
q=array[q][position];
if(q==m)
{
printf("find!\n");
break;
}
}
if(q!=m)
{
printf("unfind\n");
i=-;
}
return i;//如果匹配成功返回pattern在字符串的结束位置,否则返回-1;
}
//程序结束进行销毁二维数组
void Delete(int*** array,char *pattern)
{
int i;
int m=strlen(pattern);
for(i=m; i>=; i--)
{
free((*array)[i]);
}
free((*array));
} int main(void)
{
char a[]="defabcababacaghijkl";
char b[]="ababaca";
int **array;
int i;
printf("开始构建自动机:\n");
Create(&array,b);
printf("自动机构建完毕!\n");
int end=DFAMatcher(a,array,b);
int first=end-strlen(b)+;
if(end>=)
{
printf("输入字符串:%s\n",a);
printf("模式:%s\n",b);
printf("结果:\n");
printf("%s\n",a);
for(i=; i<strlen(a); i++)
{
if(i==end || i==first)
{
printf("|");
}
else
{
printf(" ");
}
}
printf("\nEnd Position:%d",end);
}
else
{
printf("结果出错了!");
}
Delete(&array,b);
return ;
}

代码参考:出处

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

  1. 基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤

    面临敏感词过滤的问题,最简单的方案就是对要检测的文本,遍历所有敏感词,逐个检测输入的文本是否包含指定的敏感词. 很明显上面这种实现方法的检测时间会随着敏感词库数量的增加而线性增加.系统会因此面临性能和 ...

  2. Boyer-Moore 字符串匹配算法

    字符串匹配问题的形式定义: 文本(Text)是一个长度为 n 的数组 T[1..n]: 模式(Pattern)是一个长度为 m 且 m≤n 的数组 P[1..m]: T 和 P 中的元素都属于有限的字 ...

  3. KMP单模快速字符串匹配算法

    KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...

  4. 【原创】通俗易懂的讲解KMP算法(字符串匹配算法)及代码实现

    一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想 ...

  5. 4种字符串匹配算法:KMP(下)

    回顾:4种字符串匹配算法:BS朴素 Rabin-karp(上) 4种字符串匹配算法:有限自动机(中) 1.图解 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R ...

  6. 4种字符串匹配算法:BS朴素 Rabin-karp(上)

    字符串的匹配的算法一直都是比较基础的算法,我们本科数据结构就学过了严蔚敏的KMP算法.KMP算法应该是最高效的一种算法,但是确实稍微有点难理解.所以打算,开这个博客,一步步的介绍4种匹配的算法.也是& ...

  7. 字符串匹配算法 -- Rabin-Karp 算法

    字符串匹配算法 -- Rabin-Karp 算法 参考资料 1 算法导论 2 lalor 3 记忆碎片 Rabin-karp 算法简介 在实际应用中,Rabin-Karp 算法对字符串匹配问题能较好的 ...

  8. Horspool 字符串匹配算法

    Horspool 字符串匹配算法对Boyer-Moore算法的简化算法. Horspool 算法是一种基于后缀匹配的方法,是一种“跳跃式”匹配算法,具有sub-linear亚线性时间复杂度. Hors ...

  9. web系统安全运营之基础- 基于DFA算法的高性能的敏感词,脏词的检测过滤算法类(c#).

    [概述]做好一个web系统的安全运维,除了常规的防注入,防入侵等,还有一个检测并过滤敏感词,脏词..  这件事做得不好,轻则导致一场投诉或纠纷,重则导致产品被勒令关闭停运. 废话少说,先看下代码,可以 ...

随机推荐

  1. PHP从零单排(十八)图像处理

    1.打开现有的图像 <?php header("Content-type:image/jpeg"); $img=imagecreatefromjpeg("cc.jp ...

  2. mysql只导出表结构或数据

    唯一的非导电结构指南数据 mysqldump -t 数据库名称 -uroot -p > xxx.sql 指南结构不仅指导数据 mysqldump    --opt -d  数据库名 -u -p ...

  3. C#操作Xml:XmlSerializer 对象的Xml序列化和反序列化

    这篇随笔对应的.Net命名空间是System.Xml.Serialization:文中的示例代码需要引用这个命名空间. 为什么要做序列化和反序列化? .Net程序执行时,对象都驻留在内存中:内存中的对 ...

  4. 阿里云CentOS 6.5 设备、执行Docker容器和步骤的方法

    ssh阿里云计算落地ssh username@ip uname -a 查看linux内核版本号,由于Docker推荐使用3.8内核以上,设版本号低可能会不稳定,因此须要选用yum方式升级内核. 导入 ...

  5. Visual Studio-Sequence Diagram

    UML Design Via Visual Studio-Sequence Diagram 本文主要介绍在Visual Studio中设计时序图,内容如下: 何时使用时序图 时序图元素介绍 条件.循环 ...

  6. 【百度地图API】如何制作自定义样式的公交导航结果面板?

    原文:[百度地图API]如何制作自定义样式的公交导航结果面板? 摘要: 百度地图API有默认的公交导航结果面板,但样式比较单一:而百度地图上的结果面板就比较美观.如何利用百度地图API来制作一个比较美 ...

  7. Swift语言指南(九)--基本运算符

    原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...

  8. js模块开发

    js模块开发(一) 现在嵌入页面里面的javascript代码越来越复杂,于是可能依赖也越来越严重,使用别人开发的js也越来越多,于是在理想情况下,我们只需要实现核心的业务逻辑,其他都可以加载别人已经 ...

  9. 纯CSS隔行换色

    原文:纯CSS隔行换色 <head> <meta http-equiv="Content-Type" content="text/html; chars ...

  10. 快速构建Windows 8风格应用34-构建Toast通知

    原文:快速构建Windows 8风格应用34-构建Toast通知 引言 开发过WindowsPhone应用或者使用过WindowsPhone手机的开发者都知道,我们会收到一些应用的提示信息,这些提示信 ...