BZOJ3670動物園 KMP變形

2021-08-23 12:41:48 字數 2630 閱讀 3792

description

近日,園長發現動物園中好吃懶做的動物越來越多了。例如企鵝,只會賣萌向遊客要吃的。為了整治動物園的不良風氣,讓動物們憑自己的真才實學向遊客要吃的,園長決定開設演算法班,讓動物們學習演算法。

某天,園長給動物們講解kmp演算法。

園長:「對於乙個字串s,它的長度為l。我們可以在o(l)的時間內,求出乙個名為next的陣列。有誰預習了next陣列的含義嗎?」

熊貓:「對於字串s的前i個字元構成的子串,既是它的字尾又是它的字首的字串中(它本身除外),最長的長度記作next[i]。」

園長:「非常好!那你能舉個例子嗎?」

熊貓:「例s為abcababc,則next[5]=2。因為s的前5個字元為abcab,ab既是它的字尾又是它的字首,並且找不到乙個更長的字串滿足這個性質。同理,還可得出next[1] = next[2] = next[3] = 0,next[4] = next[6] = 1,next[7] = 2,next[8] = 3。」

園長表揚了認真預習的熊貓同學。隨後,他詳細講解了如何在o(l)的時間內求出next陣列。

下課前,園長提出了乙個問題:「kmp演算法只能求出next陣列。我現在希望求出乙個更強大num陣列一一對於字串s的前i個字元構成的子串,既是它的字尾同時又是它的字首,並且該字尾與該字首不重疊,將這種字串的數量記作num[i]。例如s為aaaaa,則num[4] = 2。這是因為s的前4個字元為aaaa,其中a和aa都滿足性質『既是字尾又是字首』,同時保證這個字尾與這個字首不重疊。而aaa雖然滿足性質『既是字尾又是字首』,但遺憾的是這個字尾與這個字首重疊了,所以不能計算在內。同理,num[1] = 0,num[2] = num[3] = 1,num[5] = 2。」

最後,園長給出了獎勵條件,第乙個做對的同學獎勵巧克力一盒。聽了這句話,睡了一節課的企鵝立刻就醒過來了!但企鵝並不會做這道題,於是向參觀動物園的你尋求幫助。你能否幫助企鵝寫乙個程式求出num陣列呢?

特別地,為了避免大量的輸出,你不需要輸出num[i]分別是多少,你只需要輸出對1,000,000,007取模的結果即可。

input

第1行僅包含乙個正整數n ,表示測試資料的組數。隨後n行,每行描述一組測試資料。每組測試資料僅含有乙個字串s,s的定義詳見題目描述。資料保證s 中僅含小寫字母。輸入檔案中不會包含多餘的空行,行末不會存在多餘的空格。

output

包含 n 行,每行描述一組測試資料的答案,答案的順序應與輸入資料的順序保持一致。對於每組測試資料,僅需要輸出乙個整數,表示這組測試資料的答案對 1,000,000,007 取模的結果。輸出檔案中不應包含多餘的空行。

sample input

aaaaa

ababcababc

sample output

32 hint

n≤5,l≤1,000,000

這道題是將kmp的ne

xtn ex

t陣列變形,求的是既是它的字尾同時又是它的字首,並且該字尾與該字首不重疊,將這種字串的數量。

我們考慮還是先求出ne

xtn ex

t陣列,然後我們會發現,所有的即是字尾又是字首的字元都在ne

xtn ex

t裡,可能是ne

xt[x

] nex

t[x]

,也可能是ne

xt[n

ext[

x]] nex

t[ne

xt[x

]]

……所以我們用遞迴求出這個陣列即可。

但我們還得考慮去掉相交的,所以我們再判斷(j<<1)<=(i+1)即可。

code1:

#include

#define ll long long

using

namespace

std;

ll read()

const ll md=1e9+7;

ll n,t,l,nxt[1000010],sum[1000010],ans;

string s;

int main()

j=0;ans=1;

for(i=1;iwhile(j&&(s[i]!=s[j])) j=nxt[j];

j+=(s[i]==s[j]);

while((j<<1)>(i+1)) j=nxt[j];

ans=(ans*(sum[j]+1))%md;

}printf("%lld\n",ans);

}}

code2: 這兩個**的差別在於kmp的寫法。實際上本質是一樣的。
#include

#define maxn 1000005

#define md 1000000007

#define ll long long

using

namespace

std;

int read()

int t,l,ans,nxt[maxn],sum[maxn];

string s;

void getnext()

else k=nxt[k];

}}void kmp()

else j=nxt[j];

}}int main()

return

0;}

BZOJ3670 動物園(KMP演算法)

bzoj 神tm閱讀理解題 看完題目之後 想暴力 搞個倍增陣列來跳ne xt每次暴跳ne xt複雜度o tnlo gn 算一下,感覺複雜度差不多呀 很果斷的交了一發 然後80 分。暴力 送上 include include include include include include includ...

BZOJ3670 動物園 擴充套件KMP

先用擴充套件kmp求出si n si.n 與s s 的lcpne xti role presentation style position relative nex tine xti。考慮每個字尾si n si.n 的所有字首si k si.k 對numk n um k的貢獻,有貢獻的 k k 顯然...

洛谷2375 BZOJ 3670動物園題解

題目鏈結 洛谷鏈結 我們發現題目要我們求的num i 東西本質上其實是 求有多少以i結尾的非字首且能與字首匹配的字串,而且要求字串長度小於 i 2 我們先不考慮字串長度的限制,看所有以i結尾的非字首且能與字首匹配的字串如何計數 考慮到kmp演算法的next陣列求解的過程,大家應該都想到i結尾的非字首...