暑假 D5 NOI2014 動物園(KMP)

2022-08-01 18:12:10 字數 1282 閱讀 3878

給定乙個長為l的字串,求乙個num陣列,num[i]表示長度為i的字首中字串s『的數量,其中s『既是該字首的字首也是該字首的字尾,且|s『|*2≤i,為了方便輸出,只用輸出(num[i]+1)的乘積

第1行僅包含乙個正整數n ,表示測試資料的組數。

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

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

1 n ≤ 5, l ≤ 50

2 n ≤ 5, l ≤ 200

3 n ≤ 5, l ≤ 200

4 n ≤ 5, l ≤ 10,000

5 n ≤ 5, l ≤ 10,000

6 n ≤ 5, l ≤ 100,000

7 n ≤ 5, l ≤ 200,000

8 n ≤ 5, l ≤ 500,000

9 n ≤ 5, l ≤ 1,000,000

10 n ≤ 5, l ≤ 1,000,000

暴力:求num[i]時暴力跳fail,將滿足條件的計入

優化:利用fail樹,倍增往前跳。

正解:求i位置的fail時,利用上一次的fail,轉移方式與求fail陣列相同,長度不滿足再往前跳

性質:從乙個位置起不管跳多少次fail,對應的字首仍等於原位置的相等長度的字尾

對於cnt和fail的理解還值得思考

#includeusing

namespace

std;

#define ll long long

const

int maxn=1000005

;const

int mod=1000000007

;int

t,n;

char

s[maxn];

int fail[maxn],cnt[maxn];//

cnt為fail為i的字首的字尾等於字首的個數

//fail[i]指向的是(0,i-1)的最大字首等於最大字尾的後乙個點

intmain()

//for(int i=0;it=0

;

for(int i=0;i)

printf(

"%lld\n

",ans);}}

view code

題解 NOI2014 動物園

luogu 輸入n組資料,每組資料報含乙個字串s,對於每個s,求出它的num陣列。num陣列的定義是 字串s的前i個字元構成的子串,既是它的字尾同時又是它的字首,並且該字尾與該字首不重疊,將這種字串的數量記作num i 為了避免大量的輸出,你不需要輸出num i 分別是多少,你只需要輸出所有 num...

NOI2014 動物園題解

2種解法,sb o nlogn 和 sb o n 聽到過另一種牛逼 o n 感覺有點假就沒寫。sb o n log n 首先都知道 nxt 的指向關係可以構成一顆內向樹,隨便二分一下就行了。sb o n log n includeusing namespace std const int n 100...

題解 P2375 NOI2014 動物園

luogu 先用裸的 kmp 求出 fail next 陣列 隨便叫的無所謂啦 和不管重疊時的數量記為 ans ans 的定義類似於 fail next 然後再跑一遍,求出 frac 的數量,可結合 理解 includeusing namespace std int n,l,fail 1000010...