首页 > 编程知识 正文

像匹配算法,匈牙利匹配算法

时间:2023-05-05 19:27:53 阅读:207588 作者:2694

字符串的定位操作通常称为串的模式匹配。模式匹配的应用很常见的函数模式一般是:

int index(const string &Tag, const string &Ptn, int pos)

其中,Tag是主字符串,Ptn是子字符串,如果在主串Tag的第pos个位置后存在与子字符串Ptn相同的子串,返回它在主串第pos个字符后第一次出现的位置,否则返回-1。


一、BF算法:

暴风(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。如图所示:







int index(const string &Tag, const string &Ptn, int pos){int i = pos;//主串当前要比较的位置,初始化为posint j = 0;//子串当前要比较的位置,初始化为0int Tlen = Tag.size();//主字符串的长度int Plen = Ptn.size();//子字符串的长度while (i < Tlen && j < Plen){if (Tag[i] == Ptn[j])//如果当前字符串相同,则继续向下比较{i++;j++;}else//如果不同,把i和j退回到初始位置,重新进行比较{i = i - j + 1;j = 0;}}if (j >= Plen)//如果比较的长度已经大于子串长度,说明已经匹配成功{return (i - Plen);}else{return -1;}}

二、KMP算法:

BF算法的时间复杂度最坏情况是o(Plen*Tlen),而之所以时间复杂度是由于索引指针的回溯引起的,针对以上不足,于是出现了KMP算法。它的时间复杂度为o(Plen+Tlen)。改进之处在于:每一趟比较重出现的字符不等时,不需要回溯索引指针i,而是利用已经得到的部分匹配结果将子串向右滑动尽可能远的距离,继续进行比较。

如果采用简单的BF算法,则每趟比较i都会要退回,而采用KMP算法,每趟比较时,保持不变,只需要将j向右滑动即可,可即减少了中间一些趟次的比较。

//求next数组中各元素的值,保存在长为len的next数组中void get_next(const string &Ptn, int *next, int len){int j = 0;int k = -1;next[0] = -1;while (j<len - 1){if (k == -1 || Ptn[j] == Ptn[k]){ //如果满足上面分析的Pk = Pj的情况,则继续比较下一个字符,//并得next[j+1]=next[j]+1j++;k++;next[j] = k;}else{ //如果符合上面分析的第2种情况,则依据next[k]继续寻找下一个比较的位置k = next[k];}}}//求next数组的改进数组中各元素的值,保存在长为len的nextval数组中void get_nextval(const string &Ptn, int *nextval, int len){int j = 0;int k = -1;nextval[0] = -1;while (j<len - 1){if (k == -1 || Ptn[j] == Ptn[k]){ //如果满足上面分析的Pk = Pj的情况,则继续比较下一个字符,//并得next[j+1]=next[j]+1j++;k++;if (Ptn[j] != Ptn[k])nextval[j] = k;else //Ptn[j]与Ptn[k]相等时,直接跳到netval[k]nextval[j] = nextval[k];}else{ //如果符合上面分析的第2种情况,则依据next[k]继续寻找下一个比较的位置k = nextval[k];}}}/*返回子串Ptn在主串Tag的第pos个字符后(含第pos个位置)第一次出现的位置,若不存在,则返回-1采用KMP算法,这里的位置全部以从0开始计算为准,其中T非空,0<=pos<=Tlen*/int kmp_index(const string &Tag, const string &Ptn, int pos){int i = pos; //主串当前正待比较的位置,初始为posint j = 0; //子串当前正待比较的位置,初始为0int Tlen = Tag.size(); //主串长度int Plen = Ptn.size(); //子串长度//求next数组的值,并逐个输出int *next = (int *)malloc(Plen * sizeof(int));get_next(Ptn, next, Plen);//get_nextval(Ptn,next,Pln);int t;cout << "子串的next数组中的各元素为:";for (t = 0; t<Plen; t++)cout << next[t] << " ";cout << endl;while (i<Tlen && j<Plen){if (j == -1 || Tag[i] == Ptn[j]){ //如果当前字符相同,或者在子串的第一个字符处失配,则继续向下比较i++;j++;}else //如果当前字符不同,则i保持不变,j变为下一个开始比较的位置{//next数组时KMP算法的关键,i不回退,//而是继续与子串中的next[j]位置的字符进行比较j = next[j];}}if (j >= Plen)return (i - Plen);elsereturn -1;}
(没有写好,有时间再写,未完待续!)



版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。