利用有限自动机进行字符串匹配

     定义这里状态 的概念:状态代表当前已经匹配的字符个数。状态转移代表,在当前状态下,输入一个字符让当前状态发生变化。

关于自动机原理,请参考其他编译原理书籍


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

Q是状态的有限集合

q∈Q是一个初始状态

A属于Q是 特殊的接受状态集合

∑是有限输入字母表

有限自动机开始于状态q,每次读入输入字符串的一个字符。如果有限自动机在状态q的时候读入了字符a,则它从状态q转变为δ(q,a)。每当其当前状态q输入A时,就说自动机M接受了迄今为止所读入的字符串。没有接受的输入称为被拒绝的输入。
有限自动机M引入一个函数ф,称为终态函数,它是从∑*到Q的函数,满足ф(w)是M在扫描字符串w后终止时的状态。因此,当且仅当ф(w)∈A时,M接受字符串w。我们可以用转移函数递归定义ф:

有限自动机M引入一个函数ф,称为终态函数,它是从∑*到Q的函数,满足ф(w)是M在扫描字符串w后终止时的状态。因此,当且仅当ф(w)∈A时,M接受字符串w。我们可以用转移函数递归定义ф:

ф(ε)=q;

ф(wa)=δ(ф(w),a)



    考虑以下两种情况。第一种情况是,a=P[q+1],使得字符a继续匹配模式。在这种情况下,由于δ(q,a)=q+1,转移沿着自动机的主线继续进行。第二张情况a≠P[q=1],使得字符a不能继续匹配模式。这时我们必须 找到一个更小的 子串,它是P的前缀同时也是Ti的 后缀。因为当创建字符串匹配自动机时,预处理匹配模式和自己, 转移函数很快得出最长的这样的较小P前缀



#include<iostream>
#include<vector>
#include<map>
#include<string.h> 
using namespace std;

bool Matching_Prefix(const char *P,int k,int q,char a){
	if(k==0)
	return true;
	if(k==1){
		return P[0]==a;
	}
	return P[k-1]==a&& (strncmp(P,P+q-k+1,k-1)==0);
}

vector<map<char,int>> Compute_Transition_Function(const char *P,const char*input_character ){
	int m=strlen(P);
	int j=0,k;
	cout<<m<<endl;
	vector<map<char,int> >transition_map(m+1);
	for(int i=0;i<m;i++){ 
		j=0;
		cout<<"p:"<<i<<endl;                        //状态i 
		while(input_character[j]!='\0'){
		 k= min(m+1,i+2);
		do{
			k=k-1;
		}while(!Matching_Prefix(P,k,i,input_character[j]));
		transition_map[i][input_character[j]]=k;
		cout<<"状态p:"<<i<<",    输入字符"<<input_character[j]<<",    k:"<<k<<endl;   //输出状态转移函数 
		j++; 
		}	
	}
	return 	transition_map;
}


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 ;   //初始状态为0	
	 for(int i=0;i<n;i++){
	 q = transition_map[q][T[i]];
	 if(q==m)
	 cout<<"Pattern occurs whit shift"<<i-m<<endl;	
	 }
	 
}


int main(){
	const char *input_character="abcdefghijklmnopqrstuvwxyz";  //有限输入字母表 
	char T[]="abdfdfsdklfdjgkjgdkjerdfgfdg";
	char P[11]= "dklfdjgkj";
	vector<map<char,int>>transition_map=Compute_Transition_Function(P,input_character);
	Finite_Automaton_Matcher(T,P,transition_map);
	return 0;
	
} 

   从Finite_Automaton_Matcher简单的循环结构可以看出,对于一个长度为n的文本字符串,它的匹配时间为Θ(n),的,但是没有加上计算转移函数的预处理时间。

    预处理Computer_Transition_Function的运行时间为Θ(m^3 |∑|)。当然预处理可以改进为Θ(m|∑|),所以最后的时间为Θ(n)匹配时间加上Θ(m)的预处理时间。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值