网络与信息安全实验二基于双数组自动机原理的多模式匹配.docx
《网络与信息安全实验二基于双数组自动机原理的多模式匹配.docx》由会员分享,可在线阅读,更多相关《网络与信息安全实验二基于双数组自动机原理的多模式匹配.docx(13页珍藏版)》请在冰豆网上搜索。
网络与信息安全实验二基于双数组自动机原理的多模式匹配
网络与信息安全实验报告
(2015年度秋季学期)
一、实验内容
实验描述:
1、基于特征匹配的误用检测技术原理和方法
(1)掌握多模式匹配方法
(2)掌握基于双数组-自动机原理的多模式匹配原理
2、基于双数组-AC算法的多模式特征匹配算法实现
(1)双数组-自动机的预处理:
Next表、Base表、Check表、失效函数、输出函数构建
(2)双数组-自动机的特征扫描流程
(3)合理的数据结构
3、利用构建的自动机扫描目标文件
(1)扫描文件发现命中某个模式,需明确给出命中的模式和该模式在文件中的位置
(2)如命中多个模式,需全部列出
实验要求:
1、实验数据准备。
实验数据应简单实用:
利用ASCII字符集做为输入集,不考虑多字节编码的中文、英文字符集。
模式和待匹配文本可以只包含英文。
2、程序的输入部分(模式、待匹配文本)需以文件方式提供或者其它非固定的输入途径。
二、实验设计
AC双数组的原理与基本概念
1.转向函数
转向函数通过NEXT,BASE,CHECK来实现。
由于邻接表存储了所有节点,因此循环查找所有头节点,若next不为NULL说明不是叶节点,可计算NEXT。
若为叶节点则查找下一个状态,知道所有状态都查找过则推出。
创建NEXT表的过程先从根节点开始,一层一层的创建,同时计算BASE表中的值,并填充CHECK表中的值,每一层结束后在遍历左侧的邻接表进行下一层的NEXT表创建,知道全部状态创建完成为止。
Next为转向函数表(数组、链表),下标是位置偏移量,输出是状态值。
Base表(数组),下标是状态值,输出是Base值。
Next表中当前状态为s,输入为c时,假设应跳转为状态t,状态t在Next表中的位置=状态S的位置+状态S的Base值+输入c的ASCII码值。
Check表(数组),下标是状态值,输出是下标状态的父状态的值。
在创建的过程中,每一层的状态可能要作为下一层状态的父状态,因此在邻接表中记录NEXT中的pos,存储在AC中,方便最后特征码的检测。
2.失效函数
为了计算深度为d的s状态的失效函数值,我们考虑深度为d-1的状态r,存在某个输入a,使得g(r,a)=s。
执行以下步骤来创建失效函数:
Step1:
state=f(r)。
Step2:
f(s)=g(state,a)
其中a根据CHECK表得出,并现先行确定初始状态和第一层失效状态的失效函数为f(s)=0。
3.输出函数
输出函数以链表的方式储存。
要求遍历所有从根状态到叶状态的通路,在每个分支节点处将此状态压栈,在遍历完这一个分之后弹栈,并遍历此状态的另一分支,同时在进行到每一节点的同时将字符压栈,并与模式集进行比较,若存在此模式则链接到输出链表上。
在每一个状态不仅要比较本身的字符串与模式集,还需要比较此状态的失效状态字符串与输出链表,最终创立一个单向链表,保存所有需要的输出函数
程序流程图:
算法逻辑图
图中实线表示各个状态的转向,虚线为状态失效时的转向,大括号中的为输出表
数据结构:
AC算法中类似next数组的是一颗改造过的trie树。
用q表示模式P对应的trie状态,用L(q)表示从初始状态到q的路径上的标号组成的字符串。
SAC(q)定义为自动机中的另一个状态q',使得L(q')是L(q)的最长后缀,这是将“边界”的概念扩展到一组字符串。
SAC(q)称为q的供给状态,称q到SAC(q)的连线为供给链,称由供给链连接而成的路径为供给路径。
初始状态的供给状态为θ。
在构建AC自动机时,每构建一个节点State的fail表,就利用上述映射下标State.id将fail[id]设为failState.id。
对于output表,也是同理。
三、测试数据
输入的模式集:
stringss[4]={"he","she","his","hers"};
测试的文本:
stringtxt="ushers";
三、实验结果
根据模式集,构建转向next表,base表,check表,以及失效表,输入测试文本,最后输出结果
五、遇到的困难及解决方法、心得体会
通过此次实验,我对AC双数组算法有了更深的理解。
自动机的构建是建立在深度优先的基础上,算法构建不受模式集内容变化的影响。
扫描的时间复杂度与待测文本长度有关,算法构建与扫描时存在内存的浪费。
附件:
源代码
#include
#include
#include
#include
#include
#include
usingnamespacestd;
#defineAC_FAIL_STATE-1
#defineAC_UNDEF_FAIL-1
#defineAC_CONT_SIZE256
structac_transition
{
charcondition;
intnext;
};
enumFSAType
{
FSA_NULL=0,
FSA_NFA,
FSA_DFA
};
structac_state_finder:
publicbinary_function
{
booloperator()(constac_transition&t,charc)const
{
return(t.condition==c);
}
};
vector>goto_table;
vector>output_table;
vectorfail_table;
FSATypefsa_type=FSA_NULL;
intac_goto(int_state,char_cont);
intac_creat_goto_table(constvector&_ptns);
intac_creat_fail_table();
intac_convert_to_DFA();
intac_print_goto_table();
intac_search(conststring&_txt);
intmain(intargc,char**argv)
{
stringss[4]={"he","she","his","hers"};
vectorptns(ss,ss+4);
stringtxt="ushers";
ac_creat_goto_table(ptns);
ac_creat_fail_table();
ac_print_goto_table();
ac_search(txt);
ac_convert_to_DFA();
ac_print_goto_table();
ac_search(txt);
return0;
}
intac_goto(int_state,char_cont)
{
vector:
:
const_iteratorret=
find_if(goto_table[_state].begin(),goto_table[_state].end(),
bind2nd(ac_state_finder(),_cont));
if(goto_table[_state].end()==ret)
{
if(0==_state)
return0;
else
returnAC_FAIL_STATE;
}
else
returnret->next;
}
intac_creat_goto_table(constvector&_ptns)
{
intstate=0;
intstate_id=0;
ac_transitiont;
vectorts;
vectorss;
goto_table.push_back(ts);
output_table.push_back(ss);
state_id++;
for(vector:
:
const_iteratori=_ptns.begin();i!
=_ptns.end();++i)
{
state=0;
for(string:
:
const_iteratorj=i->begin();jend();++j)
{
intnext_state=ac_goto(state,*j);
if(0==next_state||AC_FAIL_STATE==next_state)
{
t.condition=*j;
t.next=state_id++;
goto_table[state].push_back(t);
goto_table.push_back(ts);
output_table.push_back(ss);
state=t.next;
}
else
state=next_state;
}
output_table[state].push_back(*i);
}
return0;
}
intac_creat_fail_table()
{
if(goto_table.empty())
return-1;
fail_table.resize(goto_table.size());
for(size_ti=0;ifail_table[i]=AC_UNDEF_FAIL;
queueq;
for(vector:
:
const_iteratori=goto_table[0].begin();
i!
=goto_table[0].end();++i)
{
fail_table[i->next]=0;
q.push(i->next);
}
intstate;
while(!
q.empty())
{
state=q.front();q.pop();
for(vector:
:
const_iteratori=goto_table[state].begin();
i!
=goto_table[state].end();++i)
{
if(AC_UNDEF_FAIL!
=fail_table[i->next])
continue;
q.push(i->next);
intprev_state=state,ret;
do
{
prev_state=fail_table[prev_state];
ret=ac_goto(prev_state,i->condition);
}while(AC_FAIL_STATE==ret);
fail_table[i->next]=ret;
for(vector:
:
const_iteratorj=output_table[ret].begin();
j!
=output_table[ret].end();++j)
{
vector:
:
const_iteratorsret=
find(output_table[i->next].begin(),output_table[i->next].end(),*j);
if(output_table[i->next].end()==sret)
output_table[i->next].push_back(*j);
}
}
}
fsa_type=FSA_NFA;
return0;
}
intac_convert_to_DFA()
{
if(fsa_type!
=FSA_NFA)
return-1;
if(goto_table.empty()||fail_table.empty())
return-1;
queueq;
for(vector:
:
const_iteratori=goto_table[0].begin();
i!
=goto_table[0].end();++i)
{q.push(i->next);}
intstate;
while(!
q.empty())
{
state=q.front();q.pop();
for(size_tc=0;c{
intnext_state=ac_goto(state,c);
if(next_state!
=AC_FAIL_STATE&&next_state!
=0)
q.push(next_state);
else
{
next_state=ac_goto(fail_table[state],c);
if(next_state!
=AC_FAIL_STATE&&next_state!
=0)
{
ac_transitiont;
t.condition=c;
t.next=next_state;
goto_table[state].push_back(t);
}
}
}
}
fail_table.clear();
fsa_type=FSA_DFA;
return0;
}
voidOutputMatch(int_state,size_t_pos)
{
for(vector:
:
const_iteratori=output_table[_state].begin();
i!
=output_table[_state].end();++i)
{
printf("%d%s:
%d\n",_state,i->c_str(),_pos-i->length());
}
}
intac_search(conststring&_txt)
{
if(goto_table.empty()||FSA_NULL==fsa_type)
return-1;
intstate=0;
string:
:
size_typei;
for(i=0;i<_txt.length();++i)
{
charc=_txt[i];
if(output_table[state].size()>0)
OutputMatch(state,i);
if(FSA_NFA==fsa_type)
{
while(AC_FAIL_STATE==ac_goto(state,c))
state=fail_table[state];
state=ac_goto(state,c);
}
elseif(FSA_DFA==fsa_type)
{
state=ac_goto(state,c);
if(AC_FAIL_STATE==state)
state=0;
}
}
if(output_table[state].size()>0)
OutputMatch(state,i);
return0;
}
intac_print_goto_table()
{
if(goto_table.empty())
return-1;
intstate_id=0;
for(vector>:
:
const_iteratori=goto_table.begin();
i!
=goto_table.end();++i,++state_id)
{
printf("%d:
",state_id);
if(FSA_NFA==fsa_type)
printf("%d",fail_table[state_id]);
for(vector:
:
const_iteratorj=i->begin();
j!
=i->end();++j)
{
printf("%c->%d",j->condition,j->next);
}
for(vector:
:
const_iteratorj=output_table[state_id].begin();
j!
=output_table[state_id].end();++j)
{
printf("(%s)",j->c_str());
}
printf("\n");
}
printf("\n");
return0;
}