您的位置:首页 > 游戏 > 游戏 > 企业画册设计制作_江西赣州网络公司_爱上链外链购买平台_谷歌搜索引擎入口2023

企业画册设计制作_江西赣州网络公司_爱上链外链购买平台_谷歌搜索引擎入口2023

2025/1/7 20:33:44 来源:https://blog.csdn.net/yanlou233/article/details/143494047  浏览:    关键词:企业画册设计制作_江西赣州网络公司_爱上链外链购买平台_谷歌搜索引擎入口2023
企业画册设计制作_江西赣州网络公司_爱上链外链购买平台_谷歌搜索引擎入口2023

目录

1.BF算法原理

2.KMP算法原理

3.next数组原理


1.BF算法原理

BF算法本质是上是双重for循环。只是用一个循环来实现的通过j=i-j+1;的方式将主串的下标从“头”开始遍历。

代码如下:

int BF(const char* S, const char* T) 
{if (S == NULL || T == NULL) {return -1;}int lenstr = strlen(S);int lensub = strlen(T);int i = 0;int j = 0;while (i < lenstr && j < lensub) {if (S[i] == T[j]) {i++;j++;}else {i = i - j + 1;//利用这个公式将i回退到对应的位置j = 0;		 }}if (j >= lensub)   { return i - j;}elsereturn -1;}                 

2.KMP算法原理

假设dadstr是主字符串,sonstr是子字符串,这两者是要比较的子字符串是否在主字符串中的字符串。如果当dadstr[i]!=sonstr[j]时,按照BF算法i时要回退到暴力for循环第几次开始对应的位置的,但是如果sonstr字符串是局部头尾对称的呢,比如sonstr是:abcabf我们可以知道当f与主字符串不相等时,f之前的字符串是头尾对称的,此时我们还需要将i回退吗,不需要因为既然能到f位置那么f之前的位置和主字符串肯定相等,并且abcab是对称的,我们就没必要i回退了,我们只需要将j回退到c位置再开始就是下一个比较的位置了。

换一种理解方式,假设有主字符串aweq和子字符串weq。我们可以这样去比较,如果if dadstr[i]==sonstr[j];i++,j++;    if dadstr[i]!=sonstr[j] &&  dadstr[i]!=sonstr[0] ;j=0,i++; else j=0;这一串代码的意思就是i去遍历主字符串,j去遍历子字符串,如果 i位置的主字符串和j位置的字字符串相等那么就继续往后面遍历,如果不相等i无需要回退,我直接将j回退到头重新比较。这样的比较也是符合逻辑的,但是如果是这样的两对字符串呢?    ->主字符串acbabcabcef和子字符串abcabcef我们发现我们刚刚的那个代码无法得到正确答案,为什么呢?因为如果按照刚刚那个算法j直接回退到0,但是我们发现在这种情况中,我们直接回退到0位置是错了,直接回退到0位置会导致少了一部分字符串比较而这一个字符串刚刚好是我们的答案,所以结果错了。所以我们要在此算法的基础上去讨论将j回退到什么位置才行。这就是next数组出现的理由,因为对称所以next数组就决定了j回退到正确的位置。

代码如下:

int strStr(string dadstr, string sonstr)
{int* next = new int[sonstr.size()];memset(next,0, sonstr.size()*4);GetNext(next, sonstr);int len1 = dadstr.size(); //计算出主串的长度int len2 = sonstr.size();   //计算出子串的长度if (len1 == 0 && len2 != 0) return -1;if (len1 == 0 && len2 == 0) return 0;if (len1 != 0 && len2 == 0) return 0;int j = 0;//主串的下标int i = 0;//子串的下标while (i < len1 && j < len2){如果主串和子串的字符相同或者j回退到了-1位置,我们都要把i和j进行++if ((j == -1) ||dadstr[i] == sonstr[j]){i++;j++;}else{j = next[j];//主串和子串的字符不匹配,j需要依靠next数组进行回退操作}}if (j >= len2) return i - j;//子串遍历完了else return -1;//子串没有遍历完了
}

3.next数组原理

接上面所说的KMP算法原理中next数组的由来,这里讨论怎么得出next数组。next数组中next[i]是指的到i位置时i之前的字符串中尾部是否与前面具有对称性,且是第几个对称。所以我们只需要判断sonstr[i]是否满足对称即可。

例如:abcabf  对应的next数组中的元素应该是 0 0 0 1 2 0 。

i=0时,“a”字符串中无头尾对称(一个字符不算)所以next[0]=0;

i=1时,“ab”字符串中也无头尾对称,所以next[1]=0;

i=2时,“abc”字符串中也无头尾对称,所以next[2]=0;

i=3时,“abca”字符串中尾部'a'与头部'a'对称且是第一个对称,所以next[3]=1;

i=4时,“abcab”字符串中尾部“ab”与头部“ab”对称且'b'是第二个对称,所以next[4]=2;

i=5时,“abcabf”字符串中无头尾对称,所以next[5]=0;

那么根据next数组的组成原理,我们可以写出这样的代码。

//方法一:
void Getnext(int* next, const string& t) {int i = 0;next[0] = -1;int j = -1;while(i < t.length) {if(j == -1||t.ch[i] == t.ch[j]) {i++;j++;next[i] = j;} else {j = next[j];}}
}

这就是next数组的代码,但是根据next数组的定义“next数组中next[i]是指的到i位置时的i前面字符串中尾部是否与前面具有对称性,且是第几个对称。”next[i]是到i位置时i前面的字符串的特性,这里还可以写成到i位置时包括i字符串的特性。此时创建next数组代码还可以写成这样:

//方法二:
void GetNext(int* next, const string& s)
{int size = 1;for(;size < s.size();size++){if (next[size-1] == 0){if (s[size] == s[0])next[size] = 1;elsenext[size] = 0;}else{if (s[size] == s[next[size - 1]])next[size] = next[size - 1]+1;elsenext[size] = 0;}}next[0] = -1;
}

同理不同的next数组所写的KMP算法不一样。这里以教材书上为准也就是方法一的代码。

如有错误欢迎指出。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com