日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【总结】字符串匹配: KMP 和 拓展KMP

發(fā)布時(shí)間:2024/8/23 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【总结】字符串匹配: KMP 和 拓展KMP 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
比起ac自動(dòng)機(jī),kmp就一個(gè)next數(shù)組,理解了如何初始化next后就可以搞一些模板題了,下面是還不錯(cuò)的學(xué)習(xí)資料,清晰易懂,自己用的模板也來(lái)自它:

 http://chaoswork.com/blog/2011/06/14/kmp%E7%AE%97%E6%B3%95%E5%B0%8F%E7%BB%93/

kmp模板 next[0]=-1;j=-1; for(i=0;i<m;) {while(j>=0 && p[i]!=p[j])j=next[j];i++;j++;next[i]=j; }for(i=0,flag=0,j=0;i<n;) {while(j>=0 && p[j]!=t[i])j=next[j];i++;j++;//已經(jīng)匹配了模式串的多少個(gè)if(j==m)//匹配成功 }

接下來(lái)需要更加深入地了解next數(shù)組,許多題目需要用到它的定義來(lái)預(yù)處理字符串:

?xdu 1154

顯然,用2次kmp處理處前綴和后綴在各點(diǎn)的匹配情況,用dp記錄符合要求的子串,有幾個(gè)要注意的地方:(調(diào)了2個(gè)小時(shí)T_T)

1.前綴的其實(shí)位置不但要在后綴的前面,終止位置不能超過(guò)后綴的終止位置,也就是說(shuō)前綴不能包含后綴.

2. 

View Code for(i=0,flag=0,j=0;i<n;) {while(j>=0 && p[j]!=t[i])j=next[j];i++;j++;   if(j==m)//若在此處記錄則會(huì)出現(xiàn)bug,因?yàn)榇藭r(shí)匹配完成點(diǎn)是i-1 }

CF也有一道與上面類(lèi)似的題,需要用kmp預(yù)處理最左端前綴和最右端后綴

http://codeforces.com/contest/149/problem/E

循環(huán)節(jié)問(wèn)題

它還能用來(lái)求周期字符串的循環(huán)節(jié)HDU1358:

性質(zhì):

當(dāng)且僅當(dāng)len%(len-next[len])==0時(shí),str[next[len]~len-1]為最小循環(huán)節(jié)

要證明它需要說(shuō)明3點(diǎn):

1.一個(gè)字符串str是周期串,假設(shè)s1為它的循環(huán)節(jié),則str=s1 s1...s1(n個(gè))?

推導(dǎo)出=>len%(len-next[len])==0成立.

2.next[len]~len-1為s1 ,len%(len-next[len])==0時(shí)?

推導(dǎo)出=>str為周期串,s1為最小循環(huán)節(jié)

3.如何保證是最小的.

證明:

1.由next的性質(zhì)知道,s[1~next[len]-1]與s[1~len-1]有最長(zhǎng)的相等的前綴和后綴s,很顯然s就是n-1個(gè)s1了.

2.設(shè)s1的長(zhǎng)度為L(zhǎng),由于len%L==0 , str可以分解成若干個(gè)長(zhǎng)度為L(zhǎng)的小串,設(shè)它們從左到右依次為

a1?, a2?... an

根據(jù)匹配關(guān)系得

a1=a2;

a2=a3;

..

an-1=an;

因此a1=a2=a3...=an;

3.next[len]保證了前綴與后綴最大化,如果循環(huán)節(jié)s1存在而s1內(nèi)還有循環(huán)節(jié)s1',則next[len]可以向后移動(dòng),與定義矛盾.

?

相等的循環(huán)同構(gòu)問(wèn)題

hdu3374 string problem

分析:

  最大和最小的循環(huán)同構(gòu)字符串可以分開(kāi)處理,求位置可以利用最小最大表示法(03wc論文 周源)

  求出現(xiàn)的次數(shù)可以用kmp掃一遍,但利用 循環(huán)節(jié) 可以更快地得到答案.

性質(zhì):

  字符串str由k個(gè)最小循環(huán)節(jié)s1組成,則它的相等循環(huán)同構(gòu)數(shù)為k.

證明:

  設(shè)相等循環(huán)同構(gòu)數(shù)為p,我們可以利用循環(huán)節(jié)s1構(gòu)造出k個(gè)相等的循環(huán)同構(gòu),于是p>=k;

  下面證明p<=k:

    如果p>k

    假設(shè)在移動(dòng)完s1到尾部前,出現(xiàn)了相同的循環(huán)同構(gòu)串,不妨設(shè)此時(shí)移動(dòng)的串為s2,

    則利用 循環(huán)節(jié)性質(zhì)2第1種情況的推理方法 可以知道s2為字符串的一個(gè)循環(huán)節(jié)

    且s2的長(zhǎng)度<s1,與s1為最小循環(huán)節(jié)的條件矛盾,因此p<=k.

  于是p只能等于k.

?

拓展KMP

  有很長(zhǎng)一段時(shí)間單純地以為拓展kmp只是kmp倒過(guò)來(lái)跑,后來(lái)發(fā)現(xiàn)很多問(wèn)題其實(shí)無(wú)法轉(zhuǎn)換成kmp解決,于是怒學(xué)了一下拓展kmp.

  首先比較一下kmp和拓展kmp解決的問(wèn)題:

  kmp解決了求所有主串的前綴pre[i]?(0<=i<n)的后綴與模式串前綴的最大匹配長(zhǎng)度問(wèn)題;

  拓展kmp解決了所有主串的后綴suf[i]前綴,與模式串前綴的最大匹配長(zhǎng)度問(wèn)題.

  

1 void getNext() { 2 int l = 1, r = -1, i, j; 3 4 for (next[0] = 0, i = 1; p[i]; ++i) { 5 if (i + next[i - l] - 1 < r) next[i] = next[i - l]; 6 else { 7 for (j = max(r - i + 1, 0); p[i + j] && p[i + j] == p[j]; ++j); 8 next[i] = j; l = i; r = i + j - 1; 9 } 10 } 11 next[0] = i; 12 }

?

  設(shè)模式串為str;

  定義next[i]為 str 與 它的后綴suf[i]的最大公共前綴長(zhǎng)度.

  r是當(dāng)前已經(jīng)確定匹配區(qū)間的最右端點(diǎn),l是對(duì)應(yīng)的左端點(diǎn),即?r=l+next[l]-1;

  當(dāng)要求next[i]時(shí)

  根據(jù) next定義 str[ l , l+next[l]-1 ] == str[ 0 , next[l]-1 ];

  得到 str[ i , l+next[l]-1 ] == str[ i-l , next[l]-1 ];

  設(shè)s1=str[ i , l+next[l]-1 ];?

  討論以下情況:

  1. 若 ?i在 [l,r] 區(qū)間內(nèi) ?

   next[i-l]的值我們已經(jīng)知道,這時(shí)候需要討論:

    如果 ?next[i-l] 小于 s1 的長(zhǎng)度,那么可以知道在下標(biāo)為 next[i-l] 的位置必定會(huì)失配,于是next[i]=next[i-l];

    如果 ?next[i-l] 大于或等于 s1 的長(zhǎng)度,那么直到r位置,我們都可以確定已經(jīng)匹配上了,接下來(lái)需要確定r后面

    位置的匹配情況,而此時(shí)i已經(jīng)匹配了r-i+1的長(zhǎng)度,next[i]從這個(gè)值開(kāi)始計(jì)數(shù)就可以了,計(jì)數(shù)完成后i+next[i]-1

    已經(jīng)大于r,因此要更新 ? r=i+next[i]-1 , l=i ;

  2.若 i不在[l,r]的區(qū)間內(nèi),即 i > r, 前面得到的信息無(wú)法用到,于是我們需要從頭將str[i]與str[0]進(jìn)行匹配,當(dāng)然也要記得更新l,r.

?  ?復(fù)雜度:

    2個(gè)循環(huán)變量i,j都是單調(diào)增的,而他們最多增加n次,因此 復(fù)雜度是線(xiàn)性的.

  拓展kmp求循環(huán)節(jié)的方法參考kmp求循環(huán)節(jié)部分.

  知道這些后可以來(lái)解決這個(gè)問(wèn)題

總結(jié)

以上是生活随笔為你收集整理的【总结】字符串匹配: KMP 和 拓展KMP的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。