AC算法BM算法

AC算法BM算法
AC算法BM算法

序言: ....................................................................... 错误!未定义书签。多模匹配算法之AC算法详解 (2)

算法概述 (2)

转向函数goto原理 (2)

输出函数output原理 (3)

失效函数failure原理 (3)

算法使用的存储结构 (4)

转向函数goto的实现 (5)

输出函数Output的实现 (6)

失效函数failure的实现 (6)

匹配函数的实现 (7)

总结 (8)

单模匹配之BM算法详解 (9)

算法概述 (9)

坏字符规则原理 (9)

好后缀规则原理 (10)

坏字符规则实现 (11)

好后缀规则实现 (11)

匹配函数的实现 (12)

总结 (13)

多模匹配算法之AC算法详解

算法概述

●Aho-Corasick算法

-这是一种字典匹配算法,它用于在输入文本中查找字典中的字符串。时间复杂度是线性的。该算法应用有限自动机巧妙地将字符比较转化为了状态

转移。

●该算法的基本思想

?在预处理阶段,AC自动机算法建立了三个函数,转向函数goto,失效函数failure和输出函数output,由此构造了一个树型有限自动机。

?在搜索查找阶段,则通过这三个函数的交叉使用扫描文本,定位出关键字在文本中的所有出现位置。

●字典树的构造

-要匹配的一些字符串添加到树结构中去,树边就是单词中的字符,单词中最后一个字符的连接节点添加标志,以表示改节点路径包含1个字典中的

字符串,搜索到此节点就表示找到了字典中的某个单词,可以直接输出。例:模式串集合P={he,she,his,hers},下面的分析都根据这个集合展开

图1

转向函数goto原理

我们规定g(state1,ch) = state2.:状态state1 经过字符ch 可以到达状态state2 。

(1)模式串he:g(0,h)=1 g(1,e)=2 模式串he的转向函数构造完毕;

(2)模式串she:g(0,s)=3 g(3,h)=4 g(4,e)=5 模式串she构造完毕;

(3)模式串his:g(0,h)=1 g(1,i)=6 g(6,s)=7 模式串hers构造完毕;

(4)模式串hers:g(0,h)=1 g(1,e)=2 g(2,r)=8 g(8,s)=9 模式串hers构造完毕;

注:(3)中g(0,h)为何不跳到6状态,原因(这个跳转也已存在,所以无需在添加新的状态),(4)中的g(0,h)=1 g(1,e)=2一样的原因。

整个模式串集合构造完毕。可以根据转向函数画出上面的图1。

输出函数output原理

在转向函数构造的基础上实现输出函数output()。模式串he最后的状态为状态2。

当模式匹配的时候遇到状态2。说明待匹配的字符串,已经匹配到了模式串he。在构造模式串的转向函数的结尾,来完成output函数的构建。

失效函数failure原理

算法使用的存储结构

1.AC字典树的存储结构

typedef struct

{

int acsmMaxStates; /*总的模式串的长度*/

int acsmNumStates; /*状态,实现跳转函数g*/ ACSM_PATTERN * acsmPatterns; /*模式串链表头*/

ACSM_STATETABLE * acsmStateTable; /*状态链表,g*/ }ACSM_STRUCT;

/*ACSM_STRUCT * acsm*/

/*acsm->acsmStateTable[M].NextState[i] = N; 意思就是g(M,i) = N;*/

2. 模式串存储结构

typedef struct _acsm_pattern

{

struct _acsm_pattern *next;

unsigned char *patrn; /*经过转化以后的模式串*/

unsigned char *casepatrn; /*源模式串*/

int n; /*源模式串长度*/

int nocase; /*模式串是否进行大小写转化*/ void *id; /*保留字段,未用*/

int nmatch; /*该模式串所匹配的次数*/ } ACSM_PATTERN;

3.状态表

typedef struct

{

int NextState[ ALPHABET_SIZE ]; /*下一跳*/

int FailState; /*失效函数f的跳转*/

ACSM_PATTERN *MatchList; /*输出函数的存储链表头*/ }ACSM_STATETABLE;

转向函数goto的实现

转向函数g(状态,字符) = 下一个状态的构建。

例:模式串集合(he,she,his,hers) 第一个模式串he,g(0,h)=1, g(1,e)=2;

第二个模式串she,g(0,s)=3, g(3,h)=4,g(4,e)=5;

第三个模式串his, g(0,h) =1,g(1,i)=6,g(6,s)=7;

第四个模式串hers, g(0,h) =1, g(1,e)=2,g(2,r)=8,g(8,s)=9. *如果字符匹配到了状态2,5,7,9就说明了已经匹配上了关键字。构建输出函数output。static void AddPatternStates (ACSM_STRUCT * acsm, ACSM_PATTERN * p) { unsigned char *pattern;

int state=0, next, n;

n = p->n;

pattern = p->patrn;

/*这个for循环就是检查是否前面的模式串已经存在当前的跳转,如果存在

则无需创建新的状态,如果不存在,则break跳转到下面的for循环来赋予新的跳转*/ for (; n > 0; pattern++, n--) { next = acsm->acsmStateTable[state].NextState[*pattern];

if (next == ACSM_FAIL_STATE) break;

state = next;

} /*模式串跳转状态赋值操作*/ for (; n > 0; pattern++, n--) { acsm->acsmNumStates++;

acsm->acsmStateTable[state].NextState[*pattern] = acsm->acsmNumStates;

state = acsm->acsmNumStates;

} /*增加每个模式串最后的状态,output函数的构建*/ AddMatchListEntry (acsm, state, p);

}

输出函数Output的实现

将状态state(2,5,7,9)对应的模式串px加入到链表里,链表头MatchList.

static void AddMatchListEntry (ACSM_STRUCT * acsm, int state, ACSM_PATTERN * px) { ACSM_PATTERN * p;

p = (ACSM_PATTERN *) AC_MALLOC (sizeof (ACSM_PATTERN));

MEMASSERT (p, "AddMatchListEntry");

memcpy (p, px, sizeof (ACSM_PATTERN));

p->next = acsm->acsmStateTable[state].MatchList;

acsm->acsmStateTable[state].MatchList = p; }

失效函数failure的实现

/*****************************************************************************

重点理解: (状态M 经过字符c 到达状态N。如果在状态N的时候字符串匹配失效,则判

断状态M的失效状态是否有经过字符c到达的状态X,如果有,则状态N的失效跳转必然

跳转到状态 X。如果没有则判断状态M的失效跳转的失效跳转。。。直到有一个状态经过

字符c到达的状态Q不为-1,状态N的失效就跳转到Q)。

状态节点深度为1的节点先入队列深度为1的失效跳转规定为0。

通俗的理解: (f(N) = g(f(M),s) | g(f(f(M)),s)......如果前面任意的一个跳转不为-1,

就赋值给f(N)).

*****************************************************************************/

static void Build_DFA (ACSM_STRUCT * acsm)

{ int r, s;

int i;

QUEUE q, *queue = &q;

ACSM_PATTERN * mlist=0;

ACSM_PATTERN * px=0;

/* Init a Queue */ queue_init (queue);

/*深度为1 的字符匹配失效,必然会回到深度为0的状态),将下一个状态入队列*/ for (i = 0; i < ALPHABET_SIZE; i++) { s = acsm->acsmStateTable[0].NextState[i];

if (s)

{ queue_add (queue, s);

acsm->acsmStateTable[s].FailState = 0;

} }

while (queue_count (queue) > 0)

{ r = queue_remove (queue);

for (i = 0; i < ALPHABET_SIZE; i++)

{ int fs, next;

if ((s = acsm->acsmStateTable[r].NextState[i]) != ACSM_FAIL_STATE)

/* 如果存在g(r,i) = s */ { queue_add(queue,s); /*状态s 入队列*/

fs=acsm->acsmStateTable[r].FailState;/*得到r失效的状态跳转fs*/

while ((next=acsm->acsmStateTable[fs].NextState[i]) ==

ACSM_FAIL_STATE) /*判断fs 状态经过字符i 是否有下一跳

next,直到状态next 为0 为止*/ {

fs = acsm->acsmStateTable[fs].FailState; /*如果没有,继续失

效到fs的失效跳转*/

}

acsm->acsmStateTable[s].FailState = next; /*如果有,赋值状态s

的失效跳转为状态next*/ }

else{

acsm->acsmStateTable[r].NextState[i]

=acsm->acsmStateTable[acsm->acsmStateTable[r].FailState].NextState[i];

/*状态r 经过字符i 到达不可达的状态,则g(r,i) = g(f(r),i)*/

}}} queue_free (queue);

}

匹配函数的实现

int acsmSearch (ACSM_STRUCT * acsm, unsigned char *Tx, int n,void (*PrintMatch) (ACSM_PATTERN * pattern,ACSM_PATTERN * mlist, int nline,int index))

{ int state;

ACSM_PATTERN * mlist;

unsigned char *Tend;

ACSM_STATETABLE * StateTable = acsm->acsmStateTable;

int nfound = 0;

unsigned char *T;

int index;

ConvertCaseEx (Tc, Tx, n);

T = Tc;

Tend = T + n; for (state = 0; T < Tend; T++) { state = StateTable[state].NextState[*T];

if( StateTable[state].MatchList != NULL ) { for(mlist=StateTable[state].MatchList;mlist!=NULL;mlist=mlist->next )

{ index = T - mlist->n + 1 - Tc;/*模式串在匹配串中的位置*/

nfound++;

PrintMatch (acsm->acsmPatterns,mlist, nline,index);

}

} } return nfound; }

总结

※预处理阶段:

转向函数把一个由状态和输入字符组成的二元组映射成另一个状态或者一条失败消息。

失效函数把一个状态映射成另一个状态。当转向函数报告失效时,失效函数就会被询问。

输出状态,它们表示已经有一组关键字被发现。输出函数通过把一组关键字集(可能是空集)和每个状态相联系的方法,使得这种输出状态的概念形式化。

※搜索查找阶段:

文本扫描开始时,初始状态置为状态机的当前状态,而输入文本y的首字符作为当前输入字符。然后,树型有限自动机通过对每个文本串的字符都做一次操作循环的方式来处理文本。

此算法有两个特点,一个是扫描文本时完全不需要回溯,另一个是时间复杂度为O(n),时间复杂度与关键字的数目和长度无关。

单模匹配之BM算法详解

算法概述

BM算法的基本流程: 设文本串T,模式串为P。首先将T与P进行左对齐,然后进行从右

向左比较,如下图所示:

若是某趟比较不匹配时,BM算法就采用两条启发式规则,即坏字符规则和好后缀规则,来计算模式串向右移动的距离,直到整个匹配过程的结束。

坏字符规则和好后缀规则:

图中,第一个不匹配的字符(红色部分)为坏字符,已匹配部分(绿色)为好后缀。

坏字符规则原理

BM算法从右向左扫描的过程中,若发现某个字符x不匹配,则按如下两种情况讨论:

i.如果字符x在模式P中没有出现,那么从字符x开始的m个文本显然不可能与P 匹配成功,直接全部跳过该区域即可。

ii. 如果x在模式P中出现,则以该字符进行对齐。

下图红色部分,发生了一次不匹配。

移动后如下图:

注:带匹配的串T在匹配字符b的时候,发现不匹配,查找模式串存在c字符。将c与P 中的c对齐,实际移动的距离是2;

假设1第一个字符b匹配成功,T的倒数第二个字符是c。与模式串P的a不匹配。查找模式串存在c字符,将c与p中的c对齐,实际移动的距离是1.;

假设2 前面所有的都匹配成功,只有最后一个字符不匹配,此时T的第一个字符为c,查找模式串存在c字符,将c与p中的c对齐,实际移动的距离是-2

通过假设1 和假设2可以看出,只通过坏字符移动,有时候可能会出现匹配串后移的情况。那这些实际的移动距离(2 , 1,-2)与上面表格里面给出的坏字符表中c对应的跳转3有何关系呢?与实际匹配成功的次数有关,移动距离(2 , 1 ,-2)与匹配成功次数( 0,1,4)有关,(可以理解为匹配串后移了匹配成功的次数,然后在前移坏字符跳转),所以坏字符跳转是与字符在模式串出现的位置有关,坏字符规则就是这样得到的。

好后缀规则原理

若发现某个字符不匹配的同时,已有部分字符匹配成功,则按如下两种情况讨论:

i 最长后缀匹配。

ii 如果已匹配部分没有在模式串中再出现,则跳过所有匹配的字符。

下图中,已匹配部分cab(绿色)在P中再没出现。

再看下图,其后缀T'(蓝色)与P中前缀P'(红色)匹配,则将P'移动到T'的位置。

移动后如下图:

移动一个距离接着匹配)。具体的分析在好后缀规则实现细讲。

坏字符规则实现

/*首先初始化所有的ascii坏字符跳转的长度为plen + 1,接着按照模式串中出现的字符按照从左向右依次赋值*/

int *make_skip(char *ptrn, int plen) { int *skip = (int *)malloc(256 * sizeof(int));

int *sptr = skip + 256;

if (skip == NULL) fprintf(stderr, "malloc failed!");

while (sptr -- != skip) *sptr = plen + 1;

while (plen != 0) skip[(unsigned char)*ptrn++] = plen--;

return skip;

} 好后缀规则实现

/*主要理解:指针p1, 指针p2,指针p3, 指针pptr,指针ptrn的作用*/

/*p1指针查找模式串中和带匹配的倒数第一个字符相同的字符*/

/*p2指针指向带匹配的倒数第二个字符*/

/*p3指针指向p1前面的那个字符*/

/*ptrn指针,控制指针,每次移动后的匹配串的第一个字符*/

/*pptr指针,控制指针*/

/*p2和p3内容做比较,ptrn和pptr控制做多少次比较,比如模式串abcd…nab…dqmab,已经成功匹配了dqmab。下一个字符匹配失败,查找模式串中是否存在dqmab最大后缀的匹配, 不移动nab的ab到dqmab对齐,因为字符n和字符m不同,通过指针pptr控制。abcd中的ab可以移动到dqmab的ab对齐,通过ptrn指针控制。*/

int *make_shift(char *ptrn, int plen) { int *shift = (int *)malloc(plen * sizeof(int));

int *sptr = shift + plen - 1;//shift最后

char *pptr = ptrn + plen - 1;//模串最后

char c;

if (shift == NULL) fprintf(stderr, "malloc failed!");

c = ptrn[plen - 1];//模串最后一个字符

*sptr = 1;

while (sptr -- != shift) { char *p1 = ptrn + plen - 2, *p2, *p3;

do { while (p1 >= ptrn && *p1-- != c);

p2 = ptrn + plen - 2;

p3 = p1;

while (p3 >= ptrn && *p3-- == *p2-- && p2 >=pptr);

}while (p3 >= ptrn && p2 >= pptr);

*sptr = shift + plen - sptr + p2 - p3;

pptr--;

}

return shift; }

匹配函数的实现

/*在匹配过程中,匹配失败了,取坏字符跳转和好后缀跳转中的大者*/

int mSearch(char *buf, int blen, char *ptrn, int plen, int *skip, int *shift) { int b_idx = plen;

int test_cmp_num = 0;

if (plen == 0)

return 1;

while (b_idx <= blen)

{

int p_idx = plen, skip_stride, shift_stride;

while (test_cmp_num ++,buf[--b_idx] == ptrn[--p_idx])

{ if (b_idx < 0)

return 0;

if (p_idx == 0) {

printf("compare number = %d \n",test_cmp_num);

return b_idx;

}

}

skip_stride = skip[(unsigned char)buf[b_idx]];

shift_stride = shift[p_idx];

b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;

} printf("compare number = %d \n",test_cmp_num);

return 0;

}

总结

BM算法是Boyer-Moore算法的缩写,贝叶-莫尔算法,是一种基于后缀比较的模式串匹配算

法。目前所知的最快的单键字符匹配算法。

模式匹配的KMP算法详解

模式匹配的KMP算法详解 模式匹配的KMP算法详解 这种由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现的改进的模式匹配算法简称为KMP算法。大概学过信息学的都知道,是个比较难理解的算法,今天特把它搞个彻彻底底明明白白。 注意到这是一个改进的算法,所以有必要把原来的模式匹配算法拿出来,其实理解的关键就在这里,一般的匹配算法: int Index(String S,String T,int pos)//参考《数据结构》中的程序 { i=pos;j=1;//这里的串的第1个元素下标是1 while(i<=S.Length && j<=T.Length) { if(S[i]==T[j]){++i;++j;} else{i=i-j+2;j=1;}//**************(1) } if(j>T.Length) return i-T.Length;//匹配成功 else return 0; } 匹配的过程非常清晰,关键是当‘失配’的时候程序是如何处理的?回溯,没错,注意到(1)句,为什么要回溯,看下面的例子: S:aaaaabababcaaa T:ababc aaaaabababcaaa ababc.(.表示前一个已经失配) 回溯的结果就是 aaaaabababcaaa a.(babc) 如果不回溯就是 aaaaabababcaaa aba.bc 这样就漏了一个可能匹配成功的情况 aaaaabababcaaa ababc 为什么会发生这样的情况?这是由T串本身的性质决定的,是因为T串本身有前后'部分匹配'的性质。如果T为abcdef这样的,大没有回溯的必要。

模式匹配算法的设计与实现

五、详细设计 #include #include #include #include using namespace std; #define MAX 100000 #define M 69 class String { private: int n; char *str; int *count; //记录子串在主串中出现的位置 int Find(int i,String &P); // 简单匹配算法找到最近的匹配串后立即停止,而不向下继续且缺乏一个数组记录位置 int *f ; //记录失败函数 void Fail(); int KMPFind(int i,String &P); //改进的失败函数 void ImproveFail(); int KMPFindImprove(int i,String &P); public: String(); //建立一个空串 String(const char *p); String(const String &p); //拷贝函数 ~String(); int Length() {return n;}; //返回当前串对象长度 void Output() {cout<

int KMPFindImprove(String &P); //改进的KMP匹配算法 void Output2(); //输出子串在主串中出现的位置 }; int String::KMPFindImprove(String &P) { int sum=0; int j=KMPFindImprove(0,P); while(j!=-1) { count[sum++]=j; if(j<=n-P.n) j=KMPFindImprove(j+P.n,P); } return sum; } void String::Output2() //输出子串在主串中的位置 { int i=0; while(count[i]!=count[i+1] && i

字符串的模式匹配算法

在前面的图文中,我们讲了“串”这种数据结构,其中有求“子串在主串中的位置”(字符串的模式匹配)这样的算法。解决这类问题,通常我们的方法是枚举从A串(主串)的什么位置起开始与B串(子串)匹配,然后验证是否匹配。假设A串长度为n,B串长度为m,那么这种方法的复杂度是O(m*n)的。虽然很多时候复杂度达不到m*n(验证时只看头一两个字母就发现不匹配了),但是我们有许多“最坏情况”,比如: A=“aaaaaaaaaaaaaaaaaaaaaaaaab”,B=“aaaaaaaab”。 大家可以忍受朴素模式匹配算法(前缀暴力匹配算法)的低效吗?也许可以,也许无所谓。 有三位前辈D.E.Knuth、J.H.Morris、V.R.Pratt发表一个模式匹配算法,最坏情况下是O(m+n),可以大大避免重复遍历的情况,我们把它称之为克努特-莫里斯-普拉特算法,简称KMP算法。 假如,A=“abababaababacb”,B=“ababacb”,我们来看看KMP是怎样工作的。我们用两个指针i和j分别表示,。也就是说,i是不断增加的,随着i 的增加j相应地变化,且j满足以A[i]结尾的长度为j的字符串正好匹配B串的前j个字符(j当然越大越好),现在需要检验A[i+1]和B[j+1]的关系。 例子: S=“abcdefgab” T=“abcdex” 对于要匹配的子串T来说,“abcdex”首字符“a”与后面的串“bcdex”中任意一个字符都不相等。也就是说,既然“a”不与自己后面的子串中任何一字符相等,那么对于主串S来说,前5位字符分别相等,意味着子串T的首字符“a”不可能与S串的第2到第5位的字符相等。朴素算法步骤2,3,4,5的判断都是多余,下次的起始位置就是第6个字符。 例子: S=“abcabcabc” T=“abcabx”

模式匹配KMP算法实验报告

实验四:KMP算法实验报告 一、问题描述 模式匹配两个串。 二、设计思想 这种由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现的改进的模式匹配算法简称为KM P算法。 注意到这是一个改进的算法,所以有必要把原来的模式匹配算法拿出来,其实理解的关键就在这里,一般的匹配算法: int Index(String S,String T,int pos)//参考《数据结构》中的程序 { i=pos;j=1;//这里的串的第1个元素下标是1 while(i<=S.Length && j<=T.Length) { if(S[i]==T[j]){++i;++j;} else{i=i-j+2;j=1;}//**************(1) } if(j>T.Length) return i-T.Length;//匹配成功 else return 0; } 匹配的过程非常清晰,关键是当‘失配’的时候程序是如何处理的?为什么要回溯,看下面的例子: S:aaaaabababcaaa T:ababc aaaaabababcaaa ababc.(.表示前一个已经失配) 回溯的结果就是 aaaaabababcaaa a.(babc) 如果不回溯就是 aaaaabababcaaa aba.bc 这样就漏了一个可能匹配成功的情况 aaaaabababcaaa ababc 这是由T串本身的性质决定的,是因为T串本身有前后'部分匹配'的性质。如果T为a bcdef这样的,大没有回溯的必要。 改进的地方也就是这里,我们从T串本身出发,事先就找准了T自身前后部分匹配的位置,那就可以改进算法。 如果不用回溯,那T串下一个位置从哪里开始呢? 还是上面那个例子,T为ababc,如果c失配,那就可以往前移到aba最后一个a的位置,像这样:

实验三____串的模式匹配

实验三串的模式匹配 一、实验目的 1.利用顺序结构存储串,并实现串的匹配算法。 2.掌握简单模式匹配思想,熟悉KMP算法。 二、实验要求 1.认真理解简单模式匹配思想,高效实现简单模式匹配; 2.结合参考程序调试KMP算法,努力算法思想; 3.保存程序的运行结果,并结合程序进行分析。 三、实验内容 1、通过键盘初始化目标串和模式串,通过简单模式匹配算法实现串的模式匹配,匹配成功后要求输出模式串在目标串中的位置; 2、参考程序给出了两种不同形式的next数组的计算方法,请完善程序从键盘初始化一目标串并设计匹配算法完整调试KMP算法,并与简单模式匹配算法进行比较。 参考程序: #include "stdio.h" void GetNext1(char *t,int next[])/*求模式t的next值并寸入next数组中*/ { int i=1,j=0; next[1]=0; while(i<=9)//t[0] { if(j==0||t[i]==t[j]) {++i; ++j; next[i]=j; } else j=next[j]; } } void GetNext2(char *t , int next[])/* 求模式t 的next值并放入数组next中 */ { int i=1, j = 0; next[1]= 0; /* 初始化 */ while (i<=9) /* 计算next[i+1] t[0]*/ { while (j>=1 && t[i] != t[j] ) j = next[j]; i++; j++;

if(t[i]==t[j]) next[i] = next[j]; else next[i] = j; } } void main() { char *p="abcaababc"; int i,str[10]; GetNext1(p,str); printf("\n"); for(i=1;i<10;i++) printf("%d",str[i]); GetNext2(p,str); printf("\n"); for(i=1;i<10;i++) printf("%d",str[i]); printf("\n\n"); }

串的朴素模式匹配算法(BF算法)

//算法功能:串的朴素模式匹配是最简单的一种模式匹配算法,又称为 Brute Force 算法,简称为BF算法 #include #include #define MAXL 255 #define FALSE 0 #define TRUE 1 typedef int Status; typedef unsigned char SString[MAXL+1]; //生成一个其值等于串常量strs的串T void StrAssign(SString &T, char *strs) { int i; T[0] = 0; //0号单元存储字串长度 for(i = 0; strs[i]; i++) //用数组strs给串T赋值 T[i+1] = strs[i]; T[0] = i; } //返回子串T在主串S中第pos个字符开始匹配的位置,若不存在,则返回0 int Index(SString S, SString T, int pos) { int i = pos, j = 1; while(i <= S[0] && j <= T[0]) { if(S[i] == T[j]) //继续比较后面的字符 { i++; j++; } else//指针回退,重新开始匹配 { i = i -j + 2; j = 1; } } if(j > T[0]) return i - T[0]; else return 0;

int main() { SString S, T; int m; char strs1[MAXL]; //建立主串S char strs2[MAXL]; //建立模式串T printf("请输入主串和子串:\n"); printf("主串S: "); scanf("%s", strs1); printf("子串T: "); scanf("%s", strs2); StrAssign(S, strs1); StrAssign(T, strs2); m = Index(S, T, 1); if(m) printf("主串 S = {%s}\n子串 T = {%s}\n在第 %d 个位置开始匹配!\n", strs1, strs2, m); else printf("主串 S = {%s}\n子串 T = {%s}\n匹配不成功!\n", strs1, strs2); return 0; }

串的模式匹配算法实验报告

竭诚为您提供优质文档/双击可除串的模式匹配算法实验报告 篇一:串的模式匹配算法 串的匹配算法——bruteForce(bF)算法 匹配模式的定义 设有主串s和子串T,子串T的定位就是要在主串s中找到一个与子串T相等的子串。通常把主串s称为目标串,把子串T称为模式串,因此定位也称作模式匹配。模式匹配成功是指在目标串s中找到一个模式串T;不成功则指目标串s中不存在模式串T。bF算法 brute-Force算法简称为bF算法,其基本思路是:从目标串s的第一个字符开始和模式串T中的第一个字符比较,若相等,则继续逐个比较后续的字符;否则从目标串s的第二个字符开始重新与模式串T的第一个字符进行比较。以此类推,若从模式串T的第i个字符开始,每个字符依次和目标串s中的对应字符相等,则匹配成功,该算法返回i;否则,匹配失败,算法返回0。 实现代码如下:

/*返回子串T在主串s中第pos个字符之后的位置。若不存在,则函数返回值为0./*T非空。 intindex(strings,stringT,intpos) { inti=pos;//用于主串s中当前位置下标,若pos不为1则从pos位置开始匹配intj=1;//j用于子串T中当前位置下标值while(i j=1; } if(j>T[0]) returni-T[0]; else return0; } } bF算法的时间复杂度 若n为主串长度,m为子串长度则 最好的情况是:一配就中,只比较了m次。 最坏的情况是:主串前面n-m个位置都部分匹配到子串的最后一位,即这n-m位比较了m次,最后m位也各比较了一次,还要加上m,所以总次数为:(n-m)*m+m=(n-m+1)*m从最好到最坏情况统计总的比较次数,然后取平均,得到一般情况是o(n+m).

关于快速高效的模式匹配算法的剖析与改进

关于快速高效的模式匹配算法的剖析与改进 摘要:模式匹配算法是现代化网络入侵检测中的关键环节,本文主要介绍了几种常用的模式匹配算法,并在此基础上,提出一种更快捷、更高效的改进方法,以提高模式匹配的效率与质量,确保网络安全。 关键词:模式匹配入侵检测改进 随着我国计算机与网络技术的飞速发展,网络应用已涉及到人们生产、生活的各个领域,其重要性日益凸显。随之而来的网络攻击问题也备受关注,给网络安全性带来挑战。传统的网络防御模式,主要采取身份认证、防火墙、数据加密等技术,但是与当前网络发展不适应。在此背景下,入侵检测技术营运而生,并建立在模式匹配基础上,确保检测的快捷性、准确性,应用越来越广泛。 1、模式匹配原理概述 模式匹配是入侵检测领域的重要概念,源自入侵信号的层次性。结合网络入侵检测的底层审计事件,从中提取更高层次的内容。通过高层事件形成的入侵信号,遵循一定的结构关系,将入侵信号的抽象层次进行具体划分。入侵领域大师kumar将这种入侵信号划分为四大层次,并将每一个层次与匹配模式相对应。以下将分别对四大层次进行分析: (1)存在。只要存在审计事项,就可以证明入侵行为的发生,并深层次挖掘入侵企图。存在主要对应的匹配模式就是“存在模式”。可以说,存在模式就是在固定的时间内,检查系统中的特定状态,

同时判断系统状态。 (2)序列。一些入侵的发生,是遵循一定的顺序,而组成的各种行为。具体表现在一组事件的秩序上。序列对应的是“序列模式”,在应用序列模式检测入侵时,主要关注间隔的时间与持续的时间。 (3)规则。规则表示的是一种可以扩展的表达方式,主要通过and 逻辑表达来连接一系列的描述事件规则。一般适用于这种模式的攻击信号由相关活动组成,这些活动之间往往不存在事件的顺序关系。 (4)其他。其他模式是不包含前面几种方法的攻击,在具体应用过程中,难以与其他入侵信号进行模式匹配,大多为部分实现方式。 2、几种常用的模式匹配算法 2.1 ac算法 ac算法(aho-corasick)是一种可以同时搜索若干个模式的匹配算法,最早时期在图书馆书目查询系统中应用,效果良好。通过使用ac算法,实现了利用有限状态自动机结构对所有字符串的接收过程。自动机具有结构性特征,且每一个前缀都利用唯一状态显示,甚至可同时应用于多个模式的前缀中。如果文本中的某一个字符不属于模式中预期的下一个字符范围内,或者可能出现错误链接的指向状态等,那么最长模式的前缀同时也可作为当前状态相对应的后缀。ac算法的复杂性在于o(n),预处理阶段的复杂性则在于o(m)。在采取ac算法的有限状态自动机中,应该在每一个字符的模式串中分别建立节点,提高该算法的使用效率与质量。目前,应用有限

BM模式匹配算法图解

Boyer-Moore 经典单模式匹配算法 BM模式匹配算法-原理(图解) 由于毕业设计(入侵检测)的需要,这两天仔细研究了BM模式匹配算法,稍有心得,特此记下。 首先,先简单说明一下有关BM算法的一些基本概念。 BM算法是一种精确字符串匹配算法(区别于模糊匹配)。 BM算法采用从右向左比较的方法,同时应用到了两种启发式规则,即坏字符规则和好后缀规则,来决定向右跳跃的距离。 BM算法的基本流程: 设文本串T,模式串为P。首先将T与P进行左对齐,然后进行从右向左比较,如下图所示: 若是某趟比较不匹配时,BM算法就采用两条启发式规则,即坏字符规则和好后缀规则,来计算模式串向右移动的距离,直到整个匹配过程的结束。 下面,来详细介绍一下坏字符规则和好后缀规则。 首先,诠释一下坏字符和好后缀的概念。 请看下图:

图中,第一个不匹配的字符(红色部分)为坏字符,已匹配部分(绿色)为好后缀。 1)坏字符规则(Bad Character): 在BM算法从右向左扫描的过程中,若发现某个字符x不匹配,则按如下两种情况讨论: i. 如果字符x在模式P中没有出现,那么从字符x开始的m个文本显然不可能与P匹配成功,直接全部跳过该区域即可。 ii. 如果x在模式P中出现且出现次数>=1,则以该字符所在最右边位置进行对齐。 用数学公式表示,设Skip(x)为P右移的距离,m为模式串P的长度,max(x)为字符x在P中最右位置。 可以总结为字符x出现与否,将max(x)=0作为初值即可。

例1: 下图红色部分,发生了一次不匹配。 计算移动距离Skip(c) = m-max(c)=5 - 3 = 2,则P向右移动2位。 移动后如下图: 2)好后缀规则(Good Suffix): 若发现某个字符不匹配的同时,已有部分字符匹配成功,则按如下两种情况讨论: i. 如果在P中位置t处已匹配部分P'在P中的某位置t'也出现,且位置t'的前一个字符与位置t的前一个字符不相同,则将P右移使t'对应t方才的所在的位置。 ii. 如果在P中任何位置已匹配部分P'都没有再出现,则找到与P'的后缀P''相同的P的最长前缀x,向右移动P,使x对应方才P''后缀所在的位置。

数据结构-模式匹配算法

模式匹配算法 源程序如下: #include #include int index_KMP(char *s,char *t,int pos); void get_next(char *t,int *); char s[100],t[20]; int next[20],pos=0; //主函数 main() { printf("------------------------模式匹配算法 ----------------------\n"); printf("0---匹配失败,k---匹配成功,k--指主串中第一个字符出现的位置\n"); int n; printf("请输入主串s:\n"); gets(s); printf("请输入模式串t:\n"); gets(t); get_next(t,next); n=index_KMP(s,t,pos);

printf("匹配的结果:%d\n",n); } //KMP模式匹配算法 int index_KMP(char *s,char *t,int pos) { int i=pos,j=1; while (i<=(int)strlen(s)&&j<=(int)strlen(t)) { if (j==0||s[i]==t[j-1]) { i++; j++; } else j=next[j]; } if(j>(int)strlen(t)) return i-strlen(t)+1; else return 0; }

void get_next(char *t,int *next) { int i=1,j=0; next[0]=next[1]=0; while (i<(int)strlen(t)) { if (j==0||t[i]==t[j]) { i++; j++; next[i]=j; } else j=next[j]; } } 运行效果如下:

模式匹配KMP算法实验步骤

一、问题描述 模式匹配两个串。 二、设计思想 这种由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现的改进的模式匹配算法简称为KM P算法。 注意到这是一个改进的算法,所以有必要把原来的模式匹配算法拿出来,其实理解的关键就在这里,一般的匹配算法: int Index(String S,String T,int pos)//参考《数据结构》中的程序 { i=pos;j=1;//这里的串的第1个元素下标是1 while(i<=S.Length && j<=T.Length) { if(S[i]==T[j]){++i;++j;} else{i=i-j+2;j=1;}//**************(1) } if(j>T.Length) return i-T.Length;//匹配成功 else return 0; } 匹配的过程非常清晰,关键是当‘失配’的时候程序是如何处理的?为什么要回溯,看下面的例子: S:aaaaabababcaaa T:ababc aaaaabababcaaa ababc.(.表示前一个已经失配) 回溯的结果就是 aaaaabababcaaa a.(babc) 如果不回溯就是 aaaaabababcaaa aba.bc 这样就漏了一个可能匹配成功的情况 aaaaabababcaaa ababc 这是由T串本身的性质决定的,是因为T串本身有前后'部分匹配'的性质。如果T为a bcdef这样的,大没有回溯的必要。

改进的地方也就是这里,我们从T串本身出发,事先就找准了T自身前后部分匹配的位置,那就可以改进算法。 如果不用回溯,那T串下一个位置从哪里开始呢? 还是上面那个例子,T为ababc,如果c失配,那就可以往前移到aba最后一个a的位置,像这样: ...ababd... ababc ->ababc 这样i不用回溯,j跳到前2个位置,继续匹配的过程,这就是KMP算法所在。这个当T[j]失配后,j应该往前跳的值就是j的next值,它是由T串本身固有决定的,与S串无关。 《数据结构》上给了next值的定义: 0 如果j=1 next[j]={Max{k|1aaab ->aaab ->aaab 像这样的T,前面自身部分匹配的部分不止两个,那应该往前跳到第几个呢?最近的一个,也就是说尽可能的向右滑移最短的长度。 到这里,就实现了KMP的大部分内容,然后关键的问题是如何求next值?先看如何用它来进行匹配操作。 将最前面的程序改写成: int Index_KMP(String S,String T,int pos) { i=pos;j=1;//这里的串的第1个元素下标是1 while(i<=S.Length && j<=T.Length) {

模式匹配法分析波导滤波器

Ka波段波导H面膜片滤波器的MMM分析 学号:XS13042008 :田遥岭

摘要 在平时的微波滤波器分析与设计中,很多时候都是直接使用电磁仿真软件直接仿真,但是由于数值解法的先天性缺陷,我们在仿真时可能会花相当长的时间运行仿真程序。对于一些滤波器的设计人员而言,这个缺点也是相当明显的。尤其是当滤波器阶数多了以后,电磁软件的运行时间将会相当长。 本文主要是对一定尺寸的矩形波导,通过理论分析和程序仿真研究具有一定尺寸的矩形波导滤波器的滤波特性。 按照要求,本文将对a=22.86mm、b=10.16mm的矩形波导进行具体的研究讨论:首先选定的频率围Ka波段;利用模式匹配法分析这种结构,较快速的得到这种结构的滤波特性,并与HFSS中相同结构的矩形波导滤波器的仿真结果进行比较。 通过上述的分析,将会掌握另一种较为精确的滤波器分析方法。 引言 一般来讲,微波元器件的设计先用包括等效电感的等效电路进行初步设计,在用比较严格的方法,比如模式匹配法或其他数值方法进行分析验证和优化。下面就将介绍用MMM法分析矩形波导滤波器的响应理论推导及仿真过程。

理论推导 对于对称的H 面波导阶梯如下图,其模式匹配法分析不连续性两边的场的过程如下: (1)首先进行模式分析: 当TE10模入射时,由于TE10模只有Ey 分量、无Ex 分量,而且阶梯在y 方向是均匀的,即不会激励出Ex 模式。由阶梯处的边界条件可知:在阶梯处将会激励出TEm0模式。又由于此阶梯的对称性,可由阶梯两边场模式的对称性得激励模式为21,0m TE 。 (2)模式展开: 由于场的展开方式与非对称H 面阶梯中场的推导过程相同,故可以直接给出 I 区和II 区的横向场分布: I 区的场分布为:

模式匹配算法

/** *时间:2010年8月26日7:09:57 *功能:模式匹配算法代码 */ #include"stdio.h" #include"malloc.h" void kmp(int *ikmp,char *t,int t_length) { int k=0; int q=0; ikmp[0]=k; for(q=1;q0&&t[k]!=t[q]) { k=ikmp[k]; } if(t[k]==t[q]) { k=k+1; } ikmp[q]=k; } /*测试*/ for(q=0;q

while(t[t_length]!='\0') { t_length++; } /*测试*/ printf("t_length is %d\n",t_length); /*求t的kmp值*/ ikmp=malloc(t_length*sizeof(int)); kmp(ikmp,t,t_length); /*匹配过程*/ for(q=0;q0&&t[k]!=s[q]) { k=ikmp[k-1]; } if(t[k]==s[q]) { k=k+1; } if(k==t_length) { free(ikmp); return (q-t_length+1); } } free(ikmp); return -1; } main() { int i=0; char *s;/*主串*/ char *t;/*匹配串*/ printf("input s: "); scanf("%s",s); printf("input t: "); scanf("%s",t);

C语言字符串模式匹配

数据结构面试之十四——字符串的模式匹配 题注:《面试宝典》有相关习题,但思路相对不清晰,排版有错误,作者对此参考相关书籍和自己观点进行了重写,供大家参考。 十四、字符串的模式匹配 1. 模式匹配定义——子串的定位操作称为串的模式匹配。 2. 普通字符串匹配BF算法(Brute Force 算法,即蛮力算法) 【算法思想】: 第(1)步;从主串S的第pos个字符和模式的第一个字符进行比较之,若相等,则继续逐个比较后续字符;否则从主串的下一个字符起再重新和模式串的字符比较之。 第(2)步骤;依次类推,直至模式T中的每一个字符依次和主串S中的一个连续的字符序列相等,则称匹配成功;函数值为和模式T中第一个字符相等的字符在主串S中的序号,否则称为匹配不成功,函数值为0。 比如对于主串S=”abacababc”; 模式串T=”abab”; 匹配成功,返回4。 对于主串S=”abcabcabaac”; 模式串T=”abab”; 匹配不成功,返回0。 【算法实现】: //普通字符串匹配算法的实现 int Index(char* strS, char* strT, int pos) { //返回strT在strS中第pos个字符后出现的位置。 int i = pos; int j = 0; int k = 0; int lens = strlen(strS);

int lent = strlen(strT); while(i < lens && j < lent) { if(strS[i+k] == strT[j]) { ++j; //模式串跳步 ++k; //主串(内)跳步 } else { i = i+1; j=0; //指针回溯,下一个首位字符 k=0; } }//end i if(j >= lent) { return i; } else { return 0; } }//end [算法时间复杂度]:设主串长度为m,模式串的长度为n。一般情况下n

字符串匹配算法总结

Brute Force(BF或蛮力搜索) 算法: 这是世界上最简单的算法了。 首先将匹配串和模式串左对齐,然后从左向右一个一个进行比较,如果不成功则模式串向右移动一个单位。 速度最慢。 那么,怎么改进呢? 我们注意到Brute Force 算法是每次移动一个单位,一个一个单位移动显然太慢,是不是可以找到一些办法,让每次能够让模式串多移动一些位置呢? 当然是可以的。 我们也注意到,Brute Force 是很不intelligent 的,每次匹配不成功的时候,前面匹配成功的信息都被当作废物丢弃了,当然,就如现在的变废为宝一样,我们也同样可以将前面匹配成功的信息利用起来,极大地减少计算机的处理时间,节省成本。^_^ 注意,蛮力搜索算法虽然速度慢,但其很通用,文章最后会有一些更多的关于蛮力搜索的信息。 KMP算法 首先介绍的就是KMP 算法。 这个算法实在是太有名了,大学上的算法课程除了最笨的Brute Force 算法,然后就介绍了KMP 算法。也难怪,呵呵。谁让Knuth D.E. 这么world famous 呢,不仅拿了图灵奖,而且还写出了计算机界的Bible ( 业内人士一般简称TAOCP). 稍稍提一下,有个叫的家伙,不仅拿了Turing Award ,顺手拿了个Nobel Economics Award ,做了AI 的爸爸,还是Chicago Univ 的Politics PhD ,可谓全才。 KMP 的思想是这样的: 利用不匹配字符的前面那一段字符的最长前后缀来尽可能地跳过最大的距离 比如 模式串ababac 这个时候我们发现在c 处不匹配,然后我们看c 前面那串字符串的最大相等前后缀,然后再来移动 下面的两个都是模式串,没有写出来匹配串 原始位置ababa c 移动之后aba bac 因为后缀是已经匹配了的,而前缀和后缀是相等的,所以直接把前缀移动到原来后缀处,再从原来的c 处,也就是现在的第二个b 处进行比较。这就是KMP 。 Horspool 算法。 当然,有市场就有竞争,字符串匹配这么大一个市场,不可能让BF 和KMP 全部占了,于是又出现了几个强劲的对手。 第一个登场的是 Horspool 算法的思想很简单的。不过有个创新之处就是模式串是从右向左进行比较的。很好很强大,为后来的算法影响很大。 匹配串:abcbc sdxzcxx 模式串:cbcac 这个时候我们从右向左进行对暗号,c-c ,恩对上了,第二个b-a ,不对啊,我们应该怎么办?难道就这么放弃么。于是,模式串从不匹配的那个字符开始从右向左寻找匹配串中不匹配的字符b 的位置,结果发现居然有,赶快对上赶快对上,别耽误了。 匹配串:abcbcsd xzcxx 模式串:cbcac

简单的模式匹配算法

简单的模式匹配算法_Brute-Force算法 在串的操作中,子串的定位操作Index_string(s,t),通常称之为模式匹配(其中:子串t称之为模式串)。其功能是:主串s=“c0c1...c n-1”中,去查找子串t=“t0t1...t m-1”,若找到则返回子串t在主串s中的位置,否则查找不成功,返回-1。 为了便于理解,我们举例进行说明。 1.例子 例如:主串s=”ababcabcacbab”,t=”abcac”。其匹配过程如图6-12所示。 第一趟匹配: i=2 a b a b c a b c a c b a b a b c j=2 第二趟匹配: i=1 a b a b c a b c a c b a b a j=0 第三趟匹配: i=6 a b a b c a b c a c b a b a b c a c j=4 第四趟匹配: i=3 a b a b c a b c a c b a b a j=0 第五趟匹配: i=4 a b a b c a b c a c b a b a j=0 第六趟匹配: i=10 a b a b c a b c a c b a b a b c a c j=5 图6-12 Brute-Force算法中串的匹配过程 2.算法思想 算法的基本思想是:分别设置计数指针i和j指示主串s和模式串t中当前正待比较的字符位置。从主串的第一个字符和模式的第一个字符比较,若相等,则继续逐个比较后续字符;否则从主串的下一个字符起再重新和模式串的字符比较。依次类推,直到模式串中的每个字符依次和主串中的一个连续的字符序列相等,则称匹配成功,函数值为和模式串中第一个字符相等的字符在主串中的序号,否则称匹配不成功。 这个算法简单,易于理解,但效率不高,主要原因是:主串指针i在若干个字符序列比较相等后只要有一个字符比较不等便需回溯。

串的模式匹配算法

串的匹配算法——Brute Force (BF)算法 匹配模式的定义 设有主串S和子串T,子串T的定位就是要在主串S中找到一个与子串T相等的子串。通常把主串S称为目标串,把子串T称为模式串,因此定位也称作模式匹配。模式匹配成功是指在目标串S中找到一个模式串T;不成功则指目标串S中不存在模式串T。 BF算法 Brute-Force算法简称为BF算法,其基本思路是:从目标串S的第一个字符开始和模式串T中的第一个字符比较,若相等,则继续逐个比较后续的字符;否则从目标串S的第二个字符开始重新与模式串T的第一个字符进行比较。以此类推,若从模式串T的第i个字符开始,每个字符依次和目标串S中的对应字符相等,则匹配成功,该算法返回i;否则,匹配失败,算法返回0。 实现代码如下: /*返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0. /*T非空。 int index(String S, String T ,int pos) { int i=pos; //用于主串S中当前位置下标,若pos不为1则从pos位置开始匹配int j =1; //j用于子串T中当前位置下标值 while(i<=S[0]&&j<=T[0]) //若i小于S长度且j小于T的长度时循环 { if(S[i]==T[j]) //两个字母相等则继续 { ++i; ++j; } else //指针后退重新开始匹配 { i=i-j+2; //i退回到上次匹配首位的下一位 j=1; } if(j>T[0]) return i-T[0]; else return 0; } }

BF算法的时间复杂度 若n为主串长度,m为子串长度则 最好的情况是:一配就中,只比较了m次。 最坏的情况是:主串前面n-m个位置都部分匹配到子串的最后一位,即这n-m位比较了m 次,最后m位也各比较了一次,还要加上m,所以总次数为:(n-m)*m+m=(n-m+1)*m 从最好到最坏情况统计总的比较次数,然后取平均,得到一般情况是O(n+m).

kmp模式匹配算法

KMP字符串模式匹配算法详解 2009-09-04 19:28 个人觉得这篇文章是网上的介绍有关KMP算法更让人容易理解的文章了,确实说得很“详细”,耐心地把它看完肯定会有所收获的~~,另外有关模式函数值next[i]确实有很多版本啊,在另外一些面向对象的算法描述书中也有失效函数 f(j)的说法,其实是一个意思,即 next[j]=f(j-1)+1,不过还是next[j]这种表示法好理解啊: KMP字符串模式匹配详解 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高 效算法。简单匹配算法的时间复杂度为O(m*n);KMP匹配算法。可以证明它的时间复杂度为O(m+n).。 一.简单匹配算法 先来看一个简单匹配算法的函数: int Index_BF ( char S [ ], char T [ ], int pos ) { /* 若串 S 中从第pos(S 的下标0≤pos

串匹配问题:BF算法、KMP算法、BM算法

一、实验内容和目的 1、深刻理解并掌握蛮力算法的设计思想; 2、提高应用蛮力算法设计算法的技能; 3、理解这样一个观点:用蛮力法设计的算法,一般来说,经过适度的努 力后,都可以对算法的第一个版本进行一定程度的改良,改进其时 间性能。 二、实验原理及基本技术路线图(方框原理图) 串匹配问题——给定两个串S=“s1s2…s n” 和T=“t1t2…t m”,在主 串S中查找子串T的过程称为串匹配,也称模式匹配。 串匹配问题属于易解问题。 串匹配问题的特征: (1)算法的一次执行时间不容忽视:问题规模n 很大,常常需要在 大量信息中进行匹配; (2)算法改进所取得的积累效益不容忽视:串匹配操作经常被调用,执行频率高。 BF算法: 基本思想:从主串S的第一个字符开始和模式T的第一个字符进行比 较,若相等,则继续比较两者的后续字符;若不相等,则从主串S 的第二个字符开始和模式T的第一个字符进行比较,重复上述过程,若T中的字符全部比较完毕,则说明本趟匹配成功;若最后一轮匹配 的起始位置是n-m,则主串S中剩下的字符不足够匹配整个模式T, 匹配失败。这个算法称为朴素的模式匹配算法,简称BF算法。 KMP算法: 1. 在串S和串T中分别设比较的起始下标i和j; 2. 循环直到S中所剩字符长度小于T的长度或T中所有字符均比较 完毕 2.1 如果S[i]=T[j],则继续比较S和T的下一个字符;否则 2.2 将j向右滑动到next[j]位置,即j=next[j];

2.3 如果j=0,则将i和j分别加1,准备下一趟比较; 2.4 如果T中所有字符均比较完毕,则返回匹配的起始下标;否则返回0; BM算法: BM算法与KMP算法的主要区别是匹配操作的方向不同。虽然BM算法仅把匹配操作的字符比突顺序改为从右向左,但匹配发生失败时,模式T右移的计算方法却发生了较大的变化。 设计思想:设文本串T,模式串为P。首先将T与P进行左对齐,然后进行从右向左比较,若是某趟比较不匹配时,BM算法就采用两条启发式规则,即坏字符规则和好后缀规则,来计算模式串向右移动的距离,直到整个匹配过程的结束。

简单匹配算法

3113008094 詹宏宇信安1 简单匹配算法: ?算法设计思想:等,从主串S的下一字符(pos+1)起,重新与T第一个字符比较。 ?将主串S的第pos个字符和模式T的第1个字符比较, –若相等,继续逐个比较后续字符; –若不?直到主串S的一个连续子串字符序列与模式T相等。返回值为S 中与T匹配的子序列第一个字符的序号,即匹配成功。 ?否则,匹配失败,返回值0 . int Find(char*target, char* pat) { inti=0,j=0; int lengthP=strlen(pat), lengthT=strlen(target); while(i<=lengthT-lengthP) { j=0; while(target[i]==pat[j]&&j

Kmp算法实现: 第一步,先把模式T所有可能的失配点j所对应的next[j]计算出来; 第二步:执行定位函数Index_kmp(与BF算法模块非常相似) 1. int KMPindex(SString S, SString T, int pos) 2. { 3. if (pos <1 || pos > S[0] ) exit(ERROR); 4. int i = pos, j =1; 5. while (i<= S[0] && j <= T[0]) 6. { 7. if (S[i] == T[j]) { 8. ++i; ++j; 9. } else { 10. j = next[j+1]; 11. } 12. } 13. if(j > T[0]) return i - T[0]; 14. return ERROR; 15. } 完整实现代码: // Test.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include "stdlib.h" #include using namespace std; //宏定义 #define TRUE 1 #define FALSE 0 #define OK 1

相关文档
最新文档