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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UVALive 3026 Period (KMP算法简介)

發布時間:2025/3/21 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UVALive 3026 Period (KMP算法简介) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

kmp的代碼很短,但是不太容易理解,還是先說明一下這個算法過程吧。

樸素的字符串匹配大家都懂,但是效率不高,原因在哪里?

匹配過程沒有充分利用已經匹配好的模版的信息,比如說,

i是文本串當前字符的下標,j是要匹配的模版串當前正在匹配的字符的下標。(下標都從零開始,j同時可以表示已經匹配的字符長度)

當匹配到i = 4, j = 4的時候失配了,樸素的匹配做法是往右邊移一位然后從j開始掃,這樣做效率很低。

不難發現前面已經匹配好的串ab是最長公共前綴后綴。把串移動到后綴的第一個位置正好是

樸素的匹配過程中第一次匹配能把這個前綴匹配匹配完的位置!因此令j = f[j-1] = 2。

模版串下面這個f數組又是怎么來的呢?

尋找最長公共前綴后綴過程本質上也是一個匹配。

i表示當前要求f[i]的下標,j表示之前串已經匹配的最大前綴后綴長度。(j = -1表示0號位置也沒有匹配上)

當i = 6時,之前已經匹配了j個,所以只要i只要從j下標位置開始比較就行了。當匹配的時候f[i] = j+1。

如果不匹配,利用前面已經得到的f值進行匹配。

當i = 7, j = 3時,發生失配,利用之前的f值,可以知道a是最長的前綴和后綴,那么只需要從a開始匹配,因此令j = f[j-1],

重復上述過程直到匹配或j = -1的時候為止。當前就等于: f[i] = j+1。(j=-1表示沒有匹配也是為了方便統一處理)

在代碼中,因為當j = 0的時候,j = f[j-1]不好表示,因此把整個f數組向右邊移動一位。此時只需把上述過程的j = f[j-1]替換成j = f[j]。

----------------------------------------------分割線----------------------------------------------------------------

這道題要求前綴的最小循環周期。

先構造一個循環的串,然后進行求失配函數f的過程,當第一次前綴長度等于后綴長度并且各占一半的時候,這個前綴一定是最小的循環節。(從第一個結論開始用歸納法證明)

可以歸納出一個結論:在每個循環節終止的位置 i-f[i] ==最短循環節長度。

反過來i能被(i-f[i])整除可以推出i-f[i]是最短循環節。(同樣用歸納法)

?

kmp之前不太理解,只會套。為學習ac自動機,先把的kmp基礎打好。

?

#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; int f[maxn]; char str[maxn];void getF(char *s) {f[0] = -1;for(int i = 0, j = -1; s[i]; ){while(~j && s[i] != s[j]) j = f[j];f[++i] = ++j;} }int main() {//freopen("in.txt","r",stdin);int n,kas = 0;while(scanf("%d\n",&n),n){gets(str);getF(str);printf("Test case #%d\n",++kas);for(int i = 2; i <= n; i++){if(f[i] && i%(i-f[i]) == 0)printf("%d %d\n",i,i/(i-f[i]));}putchar('\n');}return 0; }

?

轉載于:https://www.cnblogs.com/jerryRey/p/4794854.html

總結

以上是生活随笔為你收集整理的UVALive 3026 Period (KMP算法简介)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。