当前位置: 首页 > news >正文

4.7.KMP算法(新版)


一.回顾:KMP算法基于朴素模式匹配算法优化而得来的

朴素模式匹配算法核心思想:把主串中所有长度与模式串长度相等的子串与模式串进行对比,直到找到第一个完全匹配的子串为止,如果当前尝试匹配的子串在某一个位置匹配失败,就立即进行下一个子串的匹配,而且是从下一个子串的头部开始一一匹配

例1:

模式串的最后一个字符与主串中第一个和模式串长度相等的子串匹配失败:

模式串与主串中第二个与模式串长度相等的子串比较,开始从2号字符开头的子串进行比较,之所以开始匹配2号字符开头的子串,且从2号字符开始比较,是因为在主串里的字符到底是什么无法得知,所以只能从主串里与模式串长度相等的子串的第一个字符依次往后匹配:

如果以2号字符开头的这个子串在某个字符上与模式串匹配失败,同理,由于主串里的字符未知,因此只能尝试匹配以3号字符开头的子串,并且要从3号字符开始依次往后与模式串进行对比,因为主串里包含的内容不得而知:

之后以此类推找主串中是否有要找的模式串。

换一种思路:

模式串的最后一个字符与主串中第一个和模式串长度相等的子串匹配失败,那么该子串中除了最后一个字符外都与模式串中除了最后一个字符外匹配成功,因此本例中模式串匹配到第6个字符才发现匹配失败,这种情况下就可以从模式串中得知主串中的前几个字符的内容,只有最后一个字符不知道,所以就要利用好此时主串中已知的字符:

根据朴素模式匹配算法的思想,如果当前的子串匹配失败,就要取下一个符合要求的子串与模式串进行对比,此时已经知道主串中前几个字符的信息,因此就会发现模式串的第一个字符就与此时要匹配的子串不匹配,所以当前的子串就没必要继续匹配下去,直接进行第三个符合要求的子串进行与模式串匹配:

现在的子串也是知道前几个字符的信息(本例中可以知道该子串前3个字符为aab),第一个字符可以和模式串第一个字符匹配,第二个字符就与模式串不匹配了,所以这个子串也没有必要继续匹配了:

同理,开始下一个子串的匹配,该子串的前两个字符是已知的,而且前两个字符匹配成功,但该子串里的第三个字符就不得而知了,所以对于现在的这个字符来说,前两个字符匹配成功,而第三个字符是否匹配成功暂时还不知道,因此一开始只需要从第三个字符开始往后检查匹配就可以了:

总结:

如本例中,模式串在与第一个子串进行匹配时,如果发现最后一个字符不匹配,那么就意味着前5个字符已得知,此时主串中以标记2为开头的子串和以标记3为开头的子串就无需匹配了,可以直接对比以标记4为开头的子串,而且在对比以标记4为开头的子串时,只需要从第三个字符开始检查即可,因为前两个元素已经确定和模式串匹配成功,这样就省去了大量的无效匹配:

KMP算法的思想:利用好模式串本身隐含的信息,要确定模式串的某一个元素发生匹配失败时接下来要如何处理,显然最终的结论并不依赖主串的内容,和匹配的主串的哪一个位置并没有关系,只和模式串的内容有关

例2:

主串中第一个符合要求的子串与模式串匹配时,在第5个字符上匹配失败:

此时主串中的前4个元素的具体信息是可以确定的,与模式串一致,从第5个元素开始后面的信息暂时不确定:

第一个子串匹配失败,开始下一个子串的匹配,显然匹配失败:

继续下一个子串的匹配,显然也不行:

继续下一个子串的匹配,已知的字符匹配成功,而未知的字符能否匹配成功暂时不得而知,所以本例中可以从该子串的第二个字符开始检查匹配:

例3:

主串中第一个符合要求的子串与模式串匹配时,在第4个字符上匹配失败:

此时主串中的前3个元素的具体信息是可以确定的,与模式串一致,从第4个元素开始后面的信息暂时不确定:

第一个子串匹配失败,开始下一个子串的匹配,显然匹配失败:

继续下一个子串的匹配,已知的字符匹配成功,而未知的字符能否匹配成功暂时不得而知,所以本例中可以从该子串的第二个字符开始检查匹配:

例4:

主串中第一个符合要求的子串与模式串匹配时,在第3个字符上匹配失败:

此时主串中的前2个元素的具体信息是可以确定的,与模式串一致,从第3个元素开始后面的信息暂时不确定:

第一个子串匹配失败,开始下一个子串的匹配,已知的元素当中匹配失败:

继续下一个子串的匹配,此时已知的元素全部用完:

例5:

主串中第一个符合要求的子串与模式串匹配时,在第2个字符上匹配失败:

此时主串中的第1个元素的具体信息是可以确定的,与模式串一致,从第2个元素开始后面的信息暂时不确定:

继续下一个子串的匹配,此时已知的元素全部用完:

例6:

主串中第一个符合要求的子串与模式串匹配时,在第1个字符上就匹配失败,此时就只能尝试匹配下一个符合要求的子串了:

前面的5个例子中都是主串指针不变,模式串指针变,本例中为了和前5个例子中的处理逻辑类似,可以先让模式串指针为0即指向模式串第一个元素的前一个位置,之后让主串指针和模式串指针都自增即可,这样就可以实现主串指针和模式串指针同时后移:

总结:

整合:

第一个子串与模式串在第6个字符上匹配失败,按照朴素模式匹配算法需要主串指针"回溯",模式串指针变为1:

按照刚才的过程即利用主串指针不"回溯",直接主串指针不变,修改模式串指针即可,省去了无效的对比:

进行此次的匹配,最终全部匹配成功,主串指针也无需"回溯",大大提高了查找效率

通常来说主串要比模式串长很多,因此用主串指针不"回溯"的方法是非常高效的。

例7:

最终会因为模式串指针超出指定范围而停止。


二.利用代码实现主串指针不"回溯"的查找算法:

可以利用数组,该数组记录当某个元素匹配失败时模式串指针应该指向的值,注:当第一个元素就匹配失败时,就要把模式串指针设为0:

  • next数组记录当某个元素匹配失败时模式串指针应该指向的值

  • i为主串指针,j为模式串指针

  • S为主串,T为模式串

  • 例如:j为6代表此时匹配到模式串里的第6个字符,如果此时第6个字符匹配失败,那么根据j=next[j]此时j更改为3

  • 利用next数组进行匹配(主串指针不"回溯")的代码:形参中S为主串,T为模式串,next数组记录当某个元素匹配失败时模式串指针应该指向的值,函数体中i为主串指针,j为模式串指针,i和j都从1开始即从头部开始匹配,S.length表示主串的长度,T.length表示模式串的长度,S.ch[i]==T.ch[j]表示此时主串的元素等于模式串的元素


三.朴素模式匹配算法 v.s. KMP算法:

KMP算法相比于朴素模式匹配算法多了一个next数组以及对模式串指针为0时的判断,有了next数组就不需要主串指针"回溯",只需要修改模式串的指针即可:

  • 主串的长度为n,由于主串指针不"回溯",所以模式匹配过程最坏时间复杂度就是O(n)即把整个主串都走了一遍,最终算整个算法的时间复杂度时只需要相加即可

  • KMP算法最坏时间复杂度为O(m+n)

  • KMP算法在效率上要优于朴素模式匹配算法


四.求next数组(next数组记录当某个元素匹配失败时模式串指针应该指向的值):

注:next数组0索引上不存数据,从1索引开始

  • next数组的长度等于模式串长度加一,因为next数组存储数据的下标要和模式串的下标一一对应,此时模式串下标规定从1开始,而数组下标却从0开始,所以next数组的长度等于模式串长度加一,由上图也可知

  • 比如next[1]代表模式串第一个字符,在next数组中next[1]的含义是当模式串的第一个字符发生匹配失败时模式串指针应该指向哪个位置

  • 任何模式串都一样,第一个字符不匹配时,只能匹配主串里下一个符合要求的子串,因此,往后余生,next[1]都无脑写0

  • 任何模式串都一样,第二个字符不匹配时,应尝试匹配模式串的第一个字符,因此,往后余生,next[2]都无脑写1

例一:

求next[1],若模式串的第一个字符匹配失败,根据之前的分析,此时模式串指针的值赋值为0,然后模式串指针和主串指针同时自增即开始匹配往后的模式串和主串里的子串,所以next[1]为0:

求next[2],若模式串的第二个字符匹配失败,意味着这时无法得知模式串的第二个字符所在的位置对应的主串里的该位置的字符,那么就只能让模式串往后滑动一位,也就是让模式串指针为1即next[2]为1:

求next[3],若模式串的第三个字符匹配失败,此时可以由模式串得知主串里的两个字符(如下图)即分界线左边的两个字符,在分界线的左边的前两个字符,一个一个往后移动进行比对,如果比对成功就进行下一个字符的比对,如果失败直接后移模式串比对。例如本例中先移动一个字符,发现不匹配,然后继续往后移模式串,此时整个模式串就全部移动到分界线的右边了,而在分界线的右边,主串的内容就不得而知了,因此就有必要把此时主串指针所指的元素和模式串指针所指的元素进行比对,因此当模式串第三个字符匹配失败时,可以直接让模式串指针的值为1即next[3]为1:

求next[4],若模式串的第四个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前三个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,根据题意,由于无法匹配成功最终模式串会全部移动到分界线右边,而且分界线右边的字符无法确定,所以就有必要把此时主串指针所指的元素和模式串指针所指的元素进行比对,所以当模式串第四个字符匹配失败时,可以让模式串指针的值为1即next[4]为1:

求next[5],若模式串的第五个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前四个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,最终当分界线左边只剩下一个字符时开始匹配成功,由于分界线右边的字符未知,所以有必要开始模式串第二个字符的比对,因此当模式串第五个字符匹配失败时,可以让模式串指针的值为2即next[5]为2:

求next[6],若模式串的第六个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前五个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,根据题意,由于无法匹配成功模式串最终会全部移动到分界线右边,而且分界线右边的字符无法确定,所以就有必要把此时主串指针所指的元素和模式串指针所指的元素进行比对,所以当模式串第六个字符匹配失败时,可以让模式串指针的值为1即next[6]为1:

到此,求出了字符串google的next数组。

应用例一中通过字符串google求出的next数组:

首先模式串的第六个字符匹配失败,根据求出来的next数组,模式串指针指向1:

此时模式串的第一个字符匹配失败,根据求出来的next数组,模式串指针指向0:

同时模式串指针和主串指针要自增,也就是开始匹配下一个子串:

此时模式串的第五个字符匹配失败,根据求出来的next数组,模式串指针指向2:

如下:

比对后最终匹配成功:

例二:

求next[3],若模式串的第三个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前两个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,根据题意,由于无法匹配成功模式串最终会全部移动到分界线右边,而且分界线右边的字符无法确定,所以就有必要把此时主串指针所指的元素和模式串指针所指的元素进行比对,所以当模式串第三个字符匹配失败时,可以让模式串指针的值为1即next[3]为1:

求next[4],若模式串的第四个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前三个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,当模式串移动到在分界线左边只剩下一个字符时开始匹配成功,由于分界线右边的字符无法确定,所以有必要开始模式串第二个字符的比对,因此当模式串第四个字符匹配失败时,可以让模式串指针的值为2即next[4]为2:

求next[5],若模式串的第五个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前四个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,当模式串移动到在分界线左边剩下两个字符时开始匹配成功,由于分界线右边的字符无法确定,所以有必要开始模式串第三个字符的比对,因此当模式串第五个字符匹配失败时,可以让模式串指针的值为3即next[5]为3:

求next[6],若模式串的第六个字符匹配失败,此时可以在匹配失败的字符左边画一条分界线,主串中这条分界线左边的前五个字符可以确定,而分界线右边的字符就无法确定,接下来需要模式串一步一步往右移动来比对,一边移动一边比对,当模式串移动到在分界线左边剩下三个字符时开始匹配成功,由于分界线右边的字符无法确定,所以有必要开始模式串第四个字符的比对,因此当模式串第六个字符匹配失败时,可以让模式串指针的值为4即next[6]为4:

到此,求出了模式串T的next数组。


五.求next数组的总结:

注:next数组0索引上不存数据,从1索引开始


六.next数组的优化思路:利用之前已求出next数组的模式串T即abaabc

例一:

若此时在第三个字符匹配失败:

根据next数组此时模式串指针应指向1即j为1:

由于第三个字符匹配失败,所以主串指针所指的字符和模式串指针所指的字符是不相等的,既然不相等,又此时模式串指针所指的是模式串的第三个字符a,说明主串指针所指的第三个字符一定不是a,因此当第三个字符匹配失败时,接下来需要让模式串指针指向1,但这一次的匹配一定会失败,因为模式串指针此时所指的字符是第一个字符a,这是已知的,而此时主串指针所指的元素虽然未知,但它一定不是a,第一个字符匹配失败时需要模式串指针指向0,然后模式串指针和主串指针自增:

所以,一开始发现模式串第三个字符和主串第三个字符匹配失败时,又因为模式串里的第一个字符和第三个字符相等,所以模式串里的第一个字符和主串里的第三个字符也一定会匹配失败,因此,一开始发现模式串第三个字符和主串第三个字符匹配失败时就可以直接让模式串指针指向0,因为如果让模式串指针指向1时意味着接下来是让模式串第一个字符和主串第三个字符开始匹配,根据之前的分析,该匹配注定失败,当第一个字符匹配失败时,应该让模式串指针指向0,所以最好的处理方式就是直接让模式串指针指向0(这样就可以跳过多余的模式串第一个字符匹配主串第三个字符):

最终优化后,当第三个字符匹配失败时,直接让模式串指针指向0,然后模式串指针和主串指针自增,意味着跳过了多余的模式串第一个字符匹配主串第三个字符:

例二:

若此时在第五个字符匹配失败:

根据next数组此时模式串指针应指向2即j为2:

由于第五个字符匹配失败,所以主串指针所指的字符和模式串指针所指的字符是不相等的,既然不相等,又此时模式串指针所指的是模式串的第五个字符b,说明主串指针所指的第五个字符一定不是b,因此当第五个字符匹配失败时,接下来需要让模式串指针指向2,但这一次的匹配一定会失败,因为模式串指针此时所指的字符是第二个字符b,这是已知的,而此时主串指针所指的元素虽然未知,但它一定不是b,第二个字符匹配失败时需要模式串指针指向1:

最终优化后,当第五个字符匹配失败时,直接让模式串指针指向1,意味着跳过了多余的模式串第二个字符匹配主串第五个字符:

最终优化后演示:

例三:

若此时在第六个字符匹配失败,可以确定主串第六个字符一定不是c:

根据next数组此时模式串指针应指向3即j为3,模式串第三个字符为a,主串里的第六个字符一定不是c,但是否是a就无法确定了,所以此时就有必要进行匹配判断,因此当六个字符匹配失败时,让模式串指针指向3是有必要的,无需继续优化:

结论:当匹配失败时,判断模式串指针要指向的下一个模式串字符和原本失配的字符是否相等,如果这两个字符不相等,next数组的值保持不变,如果这两个字符相等,此时可以更改next数组的值实现优化

  • KMP算法的进一步优化本质是优化next数组

  • nextval数组其实就是next数组的优化,也可以把nextval数组理解为新的next数组,nextval数组可以命名为next数组


七.求nextval数组:nextval数组其实就是next数组的优化,也可以把nextval数组理解为新的next数组,nextval数组可以命名为next数组

注:nextval数组0索引上不存数据,从1索引开始,nextval数组1索引上的数据固定为0即nextval[1]=0(原理和next数组1索引上的数据固定为0的原理一样)从2索引开始就需要一步一步推导

练习1:

函数解读:

  • j为模式串指针,T.length为模式串的长度,T.ch[j]为模式串T在j索引上的字符

  • 一般都是先求出next数组,再求nextval数组

  • j代表模式串指针当前所指的字符,next[j]代表模式串指针应更改为所指向的字符

  • next数组和nextval数组所包含的内容都是一样的即把当前模式串指针的值修改为下一次要指向的值

  • 该函数中nextval数组存储的值都是从next数组得出的,也就是说nextval的元素是next[j]

  • 如果当前j所指的字符和next[j]所指的字符不相等,那么就让nextval[j]=next[j],意味着nextval数组在j索引上的值等于next数组在j索引上的值。例如上述图片中求nextval[2],此时代表模式串第二个字符匹配失败且j等于2,其中j指向第二个字符即b,next[j](即next[2])等于1即模式串指针应该改为指向模式串第一个字符即a,由于字符a和b不相等,所以nextval[2]等于next[2]即nextval[2]=1

  • 如果当前j所指的字符和next[j]所指的字符相等,那么就让nextval[j]=nextval[ next[j] ],nextval[ next[j] ]可以理解为next数组的嵌套,当j指针即模式串指针指向的字符匹配失败时需要指向next[j]所指的字符,根据题意,next[j]所指的字符注定会匹配失败,此时就需要把模式串指针改为next[ next[j] ]即nextval[ next[j] ]。例如上述图片中求nextval[3],此时代表模式串第三个字符匹配失败且j等于3,其中j指向第三个字符即a,next[j](即next[3])等于1即模式串指针应该改为指向模式串第一个字符即a,由于字符a和a相等,所以nextval[3]等于nextval[ next[3] ]即nextval[3]=0,其实不难理解,因为此时模式串第一个字符a和模式串第三个字符a相等,所以当模式串第三个字符匹配失败时,那么模式串第一个字符注定会匹配失败,所以没必要再对比模式串的第一个字符,而是直接考虑模式串第一个字符匹配失败后应该跳到哪个字符进行匹配

练习2:


八.next数组优化前后对比:

next数组未优化前:

模式串指针j指向的第四个字符和主串第四个字符匹配失败:

根据next数组,模式串指针指向3,此时模式串第三个字符和主串第四个字符匹配失败:

根据next数组,模式串指针指向2,此时模式串第二个字符和主串第四个字符匹配失败:

根据next数组,模式串指针指向1,此时模式串第一个字符和主串第四个字符匹配失败:

根据next数组,模式串指针指向0,然后模式串指针和主串指针都自增:

匹配后最终查找成功:

next数组优化后即nextval数组:

模式串指针j指向的第四个字符和主串第四个字符匹配失败:

根据next数组,模式串指针指向0,然后模式串指针和主串指针都自增:

匹配后最终查找成功:

显然省去了很多不必要的匹配过程。


相关文章:

4.7.KMP算法(新版)

一.回顾:KMP算法基于朴素模式匹配算法优化而得来的 朴素模式匹配算法核心思想:把主串中所有长度与模式串长度相等的子串与模式串进行对比,直到找到第一个完全匹配的子串为止,如果当前尝试匹配的子串在某一个位置匹配失败&#xf…...

iOS AES/CBC/CTR加解密以及AES-CMAC

感觉iOS自带的CryptoKit不好用,有个第三方库CryptoSwift还不错,好巧不巧,清理过Xcode缓存后死活下载不下来,当然也可以自己编译个Framework,但是偏偏不想用第三方库了,于是研究了一下,自带的Com…...

错误报告:WebSocket 设备连接断开处理问题

错误报告:WebSocket 设备连接断开处理问题 项目背景 设备通过自启动的客户端连接到服务器,服务器将设备的 mac_address 和设备信息存入 Redis。前端通过 Redis 接口查看设备信息并展示。 问题描述 设备连接到服务器后,前端无法立即看到设…...

点云配准网络

【论文笔记】点云配准网络 PCRNet: Point Cloud Registration Network using PointNet Encoding 2019_pcr-net-CSDN博客 【点云配准】【深度学习】Windows11下PCRNet代码Pytorch实现与源码讲解-CSDN博客 【点云配准】【深度学习】Windows11下GCNet代码Pytorch实现与源码讲解_…...

黑马Redis详细笔记(实战篇---短信登录)

目录 一.短信登录 1.1 导入项目 1.2 Session 实现短信登录 1.3 集群的 Session 共享问题 1.4 基于 Redis 实现共享 Session 登录 一.短信登录 1.1 导入项目 数据库准备 -- 创建用户表 CREATE TABLE user (id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 用户ID,phone …...

51单片机俄罗斯方块整行消除函数

/************************************************************************************************************** * 名称:flash * 功能:行清除动画 * 参数:NULL * 返回:NULL * 备注: * 采用非阻塞延时&#xff0…...

Vue 3 30天精进之旅:Day 21 - 项目实践:打造功能完备的Todo应用

前言 经过前20天的学习,我们已经掌握了Vue 3的核心概念、组合式API、路由、状态管理等关键技术。今天将通过一个完整的项目实践——Todo应用,将所学知识融会贯通。我们将为Todo应用添加编辑、删除、过滤等进阶功能,并优化代码结构。 一、项目…...

32单片机学习记录1之GPIO

32单片机学习记录1之GPIO 前置 GPIO口在单片机中扮演着什么角色? 在单片机中,GPIO口(General Purpose Input/Output) 是一种通用输入/输出接口,扮演着连接单片机与外部设备的桥梁角色。具体来说,它在单片…...

AI 编程助手 Cline

Cline 是一款集成于 Visual Studio Code(VS Code)的 AI 编程助手,旨在提升开发者的编程效率和代码质量。 主要功能: 代码生成与补全:Cline 能根据开发者的输入,自动生成代码片段或完整的函数,减…...

YOLOv11-ultralytics-8.3.67部分代码阅读笔记-patches.py

patches.py ultralytics\utils\patches.py 目录 patches.py 1.所需的库和模块 2.def imread(filename: str, flags: int cv2.IMREAD_COLOR): 3.def imwrite(filename: str, img: np.ndarray, paramsNone): 4.def imshow(winname: str, mat: np.ndarray): 5.PyTorch…...

R语言LCMM多维度潜在类别模型流行病学研究:LCA、MM方法分析纵向数据

全文代码数据:https://tecdat.cn/?p39710 在数据分析领域,当我们面对一组数据时,通常会有已知的分组情况,比如不同的治疗组、性别组或种族组等(点击文末“阅读原文”获取完整代码数据)。 然而,…...

2025 年前端开发现状分析:卷疯了还是卷麻了?

一、前端现状:框架狂飙,开发者崩溃 如果你是个前端开发者,那么你大概率经历过这些场景: 早上打开 CSDN(或者掘金,随便),发现又有新框架发布了,名字可能是 VueXNext.js 之…...

RDK新一代模型转换可视化工具!!!

作者:SkyXZ CSDN:SkyXZ~-CSDN博客 博客园:SkyXZ - 博客园 之前在使用的RDK X3的时候,吴诺老师wunuo发布了新一代量化转换工具链使用教程,这个工具真的非常的方便,能非常快速的完成X3上模型的量化…...

JVM春招快速学习指南

1.说在前面 在Java相关岗位的春/秋招面试过程中,JVM的学习是必不可少的。本文主要是通过《深入理解Java虚拟机》第三版来介绍JVM的学习路线和方法,并对没有过JVM基础的给出阅读和学习建议,尽可能更加快速高效的进行JVM的学习与秋招面试的备战…...

C#中的序列化和反序列化

序列化是指将对象转换为可存储或传输的格式,例如将对象转换为JSON字符串或字节流。反序列化则是将存储或传输的数据转换回对象的过程。这两个过程在数据持久化、数据交换以及与外部系统的通信中非常常见 把对象转换成josn字符串格式 这个过程就是序列化 josn字符…...

xcode常见设置

1、如何使用cmake构建archs为$(ARCHS_STANDARD)的xcode项目 在cmake中使用如下指令 set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD)") cmake - nomadli的博客 | nomadli Blog...

PG高可用学习@2

目录标题 一、Patroni 支持在同步复制下备库故障时自动降级为异步复制?参考依据1. PostgreSQL 官方文档2. Patroni 官方文档3. 高可用和容错设计原则 二、patroni 是如何检测备库故障的?1. 心跳机制2. 监控数据库进程状态3. 查询系统视图4. 复制延迟监测5. 网络连接…...

centos 8和centos 9 stream x64的区别

以下是 CentOS 8 与 CentOS Stream 9 的主要区别,从技术架构、更新策略到适用场景等维度进行对比: AI产品独立开发实战营 联系我了解 1. 定位与更新策略 特性CentOS 8CentOS Stream 9定位原为 RHEL 8 的免费稳定复刻版RHEL 9 的上游开发分支&#xff…...

C++基础学习记录—类

1、面向对象的三大特征:封装、继承、多态 2、类和对象 2.1、类的概念 类:类是一个抽象的概念,用于描述同一类对象的特点。 对象:根据类的概念所创造的实体。 类中包含属性和行为 属性:描述类的数据,一…...

云原生时代的后端开发:架构、工具与最佳实践

随着云计算的迅猛发展,云原生(Cloud Native)逐渐成为后端开发的主流趋势。云原生后端不仅能够提高应用的灵活性和可扩展性,还能显著优化开发和运维流程。本文将围绕云原生后端的关键概念、当前热门技术及最佳实践,帮助…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言:多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

docker详细操作--未完待续

docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

Linux基础开发工具——vim工具

文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...

Java中栈的多种实现类详解

Java中栈的多种实现类详解:Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...