字符串匹配算法 之 基于DFA(确定性有限自动机)
确定有限自动机定义: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(确定性有限自动机)的更多相关文章
- 基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤
面临敏感词过滤的问题,最简单的方案就是对要检测的文本,遍历所有敏感词,逐个检测输入的文本是否包含指定的敏感词. 很明显上面这种实现方法的检测时间会随着敏感词库数量的增加而线性增加.系统会因此面临性能和 ...
- Boyer-Moore 字符串匹配算法
字符串匹配问题的形式定义: 文本(Text)是一个长度为 n 的数组 T[1..n]: 模式(Pattern)是一个长度为 m 且 m≤n 的数组 P[1..m]: T 和 P 中的元素都属于有限的字 ...
- KMP单模快速字符串匹配算法
KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...
- 【原创】通俗易懂的讲解KMP算法(字符串匹配算法)及代码实现
一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想 ...
- 4种字符串匹配算法:KMP(下)
回顾:4种字符串匹配算法:BS朴素 Rabin-karp(上) 4种字符串匹配算法:有限自动机(中) 1.图解 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R ...
- 4种字符串匹配算法:BS朴素 Rabin-karp(上)
字符串的匹配的算法一直都是比较基础的算法,我们本科数据结构就学过了严蔚敏的KMP算法.KMP算法应该是最高效的一种算法,但是确实稍微有点难理解.所以打算,开这个博客,一步步的介绍4种匹配的算法.也是& ...
- 字符串匹配算法 -- Rabin-Karp 算法
字符串匹配算法 -- Rabin-Karp 算法 参考资料 1 算法导论 2 lalor 3 记忆碎片 Rabin-karp 算法简介 在实际应用中,Rabin-Karp 算法对字符串匹配问题能较好的 ...
- Horspool 字符串匹配算法
Horspool 字符串匹配算法对Boyer-Moore算法的简化算法. Horspool 算法是一种基于后缀匹配的方法,是一种“跳跃式”匹配算法,具有sub-linear亚线性时间复杂度. Hors ...
- web系统安全运营之基础- 基于DFA算法的高性能的敏感词,脏词的检测过滤算法类(c#).
[概述]做好一个web系统的安全运维,除了常规的防注入,防入侵等,还有一个检测并过滤敏感词,脏词.. 这件事做得不好,轻则导致一场投诉或纠纷,重则导致产品被勒令关闭停运. 废话少说,先看下代码,可以 ...
随机推荐
- java maven quartz exampe 实用指南
pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...
- python3使用smtplib发电子邮件
smtplib模块smtp简单邮件传输协议client实现.对于多功能性,有时,当你要发送带附件的邮件或图片,使用email.mime加载内容. 码,如以下: import smtplib impor ...
- 如何从 0 开始学 Ruby on Rails
如何从 0 开始学 Ruby on Rails (漫步版)Ruby 是一门编程语言,Ruby on Rails 是 Ruby 的一个 web 框架,简称 Rails. 有很多人对 Rails 感兴趣, ...
- DRP学习进化模型
曾经做的就是按照思维做的三级制,这是U .B ,D .坐在坐,开始增加设计模式,增加sqlhelper ,逐渐了解系统可分为只三层,层的,随着学习的不断深入明确了"为什么会出现分层" ...
- poj 1556 zoj1721 BellmanFord 最短路+推断直线相交
http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS Memory Limit: 10000K Total Submissions ...
- getch()、getche()和getchar()函数
原文:getch().getche()和getchar()函数 getch().getche()和getchar()函数(1) getch()和getche()函数 这两个函数都是从键盘上读入一个字符 ...
- Android中利用Handler实现消息的分发机制(三)
在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去 ...
- Monkey源码分析之事件注入
本系列的上一篇文章<Monkey源码分析之事件源>中我们描述了monkey是怎么从事件源取得命令,然后将命令转换成事件放到事件队列里面的,但是到现在位置我们还没有了解monkey里面的事件 ...
- tomcat源代码Catalina
Catalina的作用是初始化各个组件,并開始启动各个组件. 上文中介绍了Bootstrap是怎样启动Catalina的,如今来看看Catalina的作用: 1,Catalina通过Digester类 ...
- T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst、语言版本影响!
原文:T-SQL: 17 个与日期时间相关的自定义函数(UDF),周日作为周的最后一天,均不受 @@DateFirst.语言版本影响! CSDN 的 Blog 太滥了!无时不刻地在坏! 开始抢救性搬家 ...