引言:

本文参考自《算法导论》中 “32.3 利用有限自动机进行字符串匹配” ,其目的不仅仅是为了改善常规算法的时间复杂度问题,更是为了给在解决类似情况提供一个有限自动机方案的参考。

很多字符串匹配算法都要建立一个有限自动机,它是一个处理信息的简单机器,通过对文本字符串 T 进行扫描,找出模式 P 的所有出现位置。这些字符串匹配的自动机都非常有效:它们只对每个文本字符检查一次,并且检查每个文本字符时所需的时间为常数。因此,在模式预处理完成并建立好自动机后进行匹配所需要的时间为 O(n) 。

1、朴素字符串匹配算法:

朴素字符串匹配算法时通过一个循环找到所有有效偏移,
该循环对 n-m+1 个可能的 s 进行检测,看是否满足条件 P[1…m] = T[s+1…s+m]。

朴素字符串匹配算法伪代码:

NAIVE-STRING-MATCHER(T,P)n=T.lengthm=P.lengthfor s = 0 to n-mif p[1...m] == T[s+1,s+m]print "Pattern occurs with shift" s

最坏的情况下,朴素字符串匹配算法运行时间为 O((n-m+1)m)。

2、有限自动机:

一个有限自动机 M 是一个 5 元组(Q,q, A, ∑,δ)

Q 是状态的有限集合
q∈Q 是一个初始状态
A 包含于 Q 是一个特殊的接受状态集合
∑ 是有限输入字母表
δ 是一个从 Q✖∑ 到 Q 的函数,称为 M 的转移函数

下图为有限自动机的状态转移图,模式串为 ababaca 。

转移函数算法伪代码:

其中, Pk ⊇ Pqa 表示 Pk是 Pqa的后缀。

COMPUTE-TRANSITION-FUNCTION(P,∑)m = P.lengthfor q = 0 to mfor each charater a∈∑k = min(m+1,q+2)repeatk = k - 1until Pk ⊇ Pqaδ(q,a) = kreturn δ

有限自动机算法伪代码:

FINITE-AUTOMATON-MATCHER(T,δ,m)n = T.lengthq = 0for i = 1 to nq = δ(q,t[i])if q == mprint "Pattern occurs with shift" i-m

3、详细代码:

转载自 https://blog.csdn.net/giftedpanda/article/details/86774815

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>using namespace std;bool Matching_Prefix_Suffix(char* P,int k,int q,char c)
{                               //P为模式串 K为要验证的前缀和后缀的字符串长度if(k==0)                    //q为当前自动机主线长度return true;              //k=0 空字符串 前缀和后缀肯定相等if(k==1){                //只有一个字符串 证明自动机刚好开始创建return P[0]==c;      //如果模式串的第一个和其中的c相等 前缀等于后缀}return P[k-1]==c&& (!strncmp(P,P+q-k+1,k-1));    //检验P[0...k-1]==P[q-k+1...q]
}vector<map<char,int> > Compute_Transition_Function( char *P,const char* input_character)
{                                //计算转移函数的值int m=strlen(P);                //模式串的长度int j=0,k;printf("The main length of Finite_Automaton_Matcher is %d\n",m);vector<map<char,int> >transition_map(m+1);         //创建一个vector 一共有m+1个数据for(int i=0;i<m;i++){                   //对于模式串的长度j=0;while(input_character[j]!='\0'){      //对于输入串的每一种可能字符k= min(m+1,i+2);               //因为对于长度为i的字符串 它的转移函数最大值为ido{                          //数组下标从0开始 再加上后面k一来就减1  所以为i+2k=k-1;                  //找到一个最大值k使得模式串的P[0...k]==P[...n-1]}while(!Matching_Prefix_Suffix(P,k,i,input_character[j]));transition_map[i][input_character[j]]=k;j++;}}return  transition_map;           //返回一个vector 每一个元素为 map<char,int>
}                                     //char 为自动机中的字符 int 为转移函数值void Finite_Automaton_Matcher(char* T,char* P,vector<map<char,int> >transition_map)
{int n=strlen(T);                           //文本串长度int m=strlen(P);                           //模式串长度int q=0;                                   //转移函数的值for(int i=0;i<n;i++){                    //对于文本串中的每一个字符q = transition_map[q][T[i]];             //迭代 前一个字符的转移函数值if(q==m)                                //转移函数的值等于模式串的长度printf("Pattern occurs with shift %d\n",i+1-m);   //模式串的有效位移为i-m+1}
}int main()
{const char* input_character="abc";        //输入字母表char T[]="abababacaba";                  //文本串char P[]="ababaca";                      //模式串vector<map<char,int> >transition_map=Compute_Transition_Function(P,input_character);Finite_Automaton_Matcher(T,P,transition_map);return 0;
}

此外,有关字符串匹配的 KMP 算法,请参见:

https://blog.csdn.net/qq_30534935/article/details/100713917

有限自动机字符串匹配相关推荐

  1. 字符串——字符串匹配

    文章目录 字符串匹配 一.基本概念 字符串匹配问题 符号和术语 后缀重叠引理 二.朴素字符串匹配算法 三.Rabin-Karp算法(字符串Hash算法) 进制Hash 质数Hash 四.利用有限自动机 ...

  2. java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配

    java中字符串的精确匹配 在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论String性能调优. 我们将专注于如何有效地处理字符串创建, 字符串更改和字符串匹配操作. ...

  3. Java最佳实践–字符串性能和精确字符串匹配

    在使用Java编程语言时,我们将继续讨论与建议的实践有关的系列文章,我们将讨论String性能调优. 我们将专注于如何有效地处理字符串创建, 字符串更改和字符串匹配操作. 此外,我们将提供我们自己的用 ...

  4. 算法导论(三)字符串匹配

    字符串匹配方法对于在编辑文本程序时,能极大的提升响应效率,如网址查询搜索引擎,DNA序列匹配等. 基本定义 字符串匹配问题的形式定义: 文本(Text)是一个长度为 n 的数组 T[1..n]: 模式 ...

  5. 字符串(字符串匹配)

    一.字符串匹配问题.基础 1.假设文本是一个长度为n的数组T,而模式是长度为m的数组P,我们希望在文本T中寻找模式P 如果P出现在T中的第s个位置,那么我们称其有效偏移为s,在其他不匹配的位置称为无效 ...

  6. CCF - 201409-3 - 字符串匹配

    问题描述 试题编号: 201409-3 试题名称: 字符串匹配 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你 ...

  7. 字符串匹配shiftand算法

    令人惊叹的Shift-And/Shift-Or 写在前面:Shift-And/Shift-Or是如此令人惊叹的算法,在KMP基础上开始一段神奇之旅. 目的:以Shift-And算法为载体,试图在减少思 ...

  8. 字符串匹配数据结构 --Trie树 高效实现搜索词提示 / IDE自动补全

    文章目录 1. 算法背景 2. Trie 树实现原理 2.1 Trie 树的构建 2.2 Trie树的查找 2.3 Trie树的遍历 2.4 Trie树的时间/空间复杂度 2.5 Trie 树 Vs ...

  9. 2021年度训练联盟热身训练赛第四场 H - Rock Paper Scissors(字符串匹配,FFT)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 2021年度训练联盟热身训练赛第四场 H - Rock Paper Scissors(字符串匹配,FF ...

  10. Rabin-Karp ( 字符串匹配 )详解

    字符串匹配,例从 字符串S 中( 长度为 n ),找到 字符串T ( 长度为 m ) 经典思路:遍历 字符串 S,对于每个都为起点,匹配一次,则 O( n m )的复杂度 但是这样我们就对 字符 重复 ...

最新文章

  1. C++——简单数据类型及布尔类型
  2. C++/C++11中std::exception的使用
  3. c++ mqtt客户端_MQTT安全性设计详解
  4. Leetcode 455.分发饼干 (每日一题 20210708 同类型题)
  5. 【快速入门Linux】2_Linux命令—基本使用
  6. 一直弹出adb已停止工作(远程主机强迫关闭现有的连接)的最简单完美解决法
  7. Java Wbe 学习心得 day06
  8. 苹果录制屏幕在哪设置_屏幕录像专家如何录全屏 屏幕录像专家全屏录制设置方法...
  9. 百度竞价推广:关键词首页指导价分析及竞价出价技巧
  10. kotlin遍历数据同时删除之利用kotlin迭代器安全删除
  11. pytorch 常用目标检测评价指标总结
  12. 微信中屏蔽分享按钮一把梭快速干
  13. Android在线工具
  14. 大数据学习入门规划?和学习路线
  15. linux配置4g网络命令_Linux常用操作练习汇总
  16. luogu P2056 采花
  17. 正态分布均值μ的贝叶斯Bayes估计推导
  18. 如何抓住下一波零售风口?看影刀RPA玩转零售自动化
  19. 了解CAP(一致性、可用性、分区容错性)
  20. 计算机等级考试到底是怎么考的?

热门文章

  1. 疫情期间大学生在线学习效果调查报告
  2. 全球主要城市时区时差转换计算表
  3. 通过Java编程实现发送短信功能(转发)
  4. 朋友让帮忙写个理发店的会员信息管理系统...
  5. 一个美国人在上海-American McGee
  6. 浅谈程序员常去的社区
  7. 稳定排序和不稳定排序
  8. 选择排序为什么是不稳定的?
  9. 2019最受欢迎的企业网站CMS建站系统排行榜
  10. 数据库 - BC范式(BCNF)