确定有限自动机定义: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. POJ 1066 Treasure Hunt(相交线段&amp;&amp;更改)

    Treasure Hunt 大意:在一个矩形区域内.有n条线段,线段的端点是在矩形边上的,有一个特殊点,问从这个点到矩形边的最少经过的线段条数最少的书目,穿越仅仅能在中点穿越. 思路:须要巧妙的转换一 ...

  2. 第18章 备忘录模式(Memento Pattern)

    原文  第18章 备忘录模式(Memento Pattern) 备忘录模式       概述: 备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Toke ...

  3. HDU多赛学校9 HDU4969 Just a Joke 【数学积分】

    数学题目 意甲冠军:的男孩向圆上的女孩跑去,保持男孩女孩圆心在同一条直线上.这过程中,男孩女孩均匀速 给出男孩女孩速度,圆的半径,男孩最长能跑的距离 问男孩是否能跑到女孩那里 能够用积分来解这道题,我 ...

  4. 项目开发经常使用PHP功能

    日期操作 为了便于存储.比较和交付.我们通常使用strtotime()功能转换的日期UNIX时间戳.有仅用于在显示给用户时date()成经常使用的时间格式. strtotime()  函数将不论什么英 ...

  5. js中从blob提取二进制

    文章结构: 一.所遇到的问题 二.解决方法 一. 服务器端通过websocket向浏览器端传输图片(二进制),需要根据不同的图片把图片显示在不同的位置,可行的一个方法是先把图片转化成二进制数组,再把二 ...

  6. FTP下载帮助类

    using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net ...

  7. my97 日期控件

    官网:http://www.my97.net/   好多广告啊! 文档地址: http://www.mysuc.com/test/My97DatePicker/

  8. NPOI mvc easyui 根据Excel模板 生成Excel

    1.首先下载 NPOI  https://npoi.codeplex.com/releases  只要dll 就好 示例代码库太难懂了. NPOI 是一个开源  免费的 东西.而且不依赖 office ...

  9. SQL语句分享[不定期更新]

    查询临时表 if object_id('')>0 查询表中的数据 select 'insert into ta1(col1,col2,col3) values('''+ltrim(列1)+''' ...

  10. POJ 3067 Japan 树状数组求逆序对

    题目大意:有两排城市,这两排城市之间有一些路相互连接着,求有多少条路相互交叉. 思路:把全部的路先依照x值从小到大排序,x值同样的依照y值从小到大排序,然后插入边的时候,先找有多少比自己y值小的,这些 ...