字符串匹配算法 之 基于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系统的安全运维,除了常规的防注入,防入侵等,还有一个检测并过滤敏感词,脏词.. 这件事做得不好,轻则导致一场投诉或纠纷,重则导致产品被勒令关闭停运. 废话少说,先看下代码,可以 ...
随机推荐
- SICP 练习 (2.12)解决摘要 :不同的实现时间
SICP 2.12 要求我们定义一个构造函数make-center-percent,它接收两个參数,分别代表中心点和一个误差百分比.我们须要通过这个构造函数产生一个区间.此外还须要定义一个选择函数pe ...
- hdu 1814 Peaceful Commission (2-sat 输出字典序最小的路径)
Peaceful Commission Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- linux_sed 正则替换
目标 替换 test.data文件中的 原正则: (\d{4}[^)]*?) sed不支持 \d 改为0-9 测试 :head test.data| sed -r "s/([0-9]{4}[ ...
- SettingsProvider该CRUD
转载请注明出处:http://blog.csdn.net/droyon/article/details/35558697 什么时候delete要么update时间.需要清空缓存并重新加载数据. 1.i ...
- MVC 缓存1
MVC 缓存 为什么要讲缓存.缓存到底有什么作用? 下面我们来说一个场景我们有一个首页菜单的布局基本是不会经常发生的变化,如果动态生成的 Web 页被频繁请求并且构建时需要耗用大量的系统资源,那么,如 ...
- MongoDB学习笔记<四>
今天继续学习MongoDB的相关知识,主要包含例如以下: --find具体解释 --分页与排序 --游标和其它知识 1.指定返回的键 db.person.find({},{"_id" ...
- windows下利用OpenVPN搭建VPNserver
一.OpenVPN是一款功能强大,可跨平台(支持Win 2000/XP/2003, Linux, Mac OS X, Solaris, FreeBSD, NetBSD, 和 OpenBSD)使用的SS ...
- 通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 ‘incorrect string value: '\xF0...
原文:[原创]通俗易懂地解决中文乱码问题(2) --- 分析解决Mysql插入移动端表情符报错 'incorrect string value: '\xF0... 这篇blog重点在解决问题,如果你对 ...
- Android ProgressBar 反向进度条/进度条从右到左走
近期的项目,有个需求须要使用条状图显示比例,而且右对齐,见下图: 我想到了使用进度条,这样不就不须要在代码动态绘制条状了,省了非常多活. 那么进度条如何从右向左显示呢? 方案一: 将ProgressB ...
- 移植MonkeyRunner的图片对比和获取子图功能的实现-Appium篇
如果你的目标测试app有很多imageview组成的话,这个时候monkeyrunner的截图比较功能就体现出来了.而其他几个流行的框架如Robotium,UIAutomator以及Appium都提供 ...