給定乙個長為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的理解還值得思考
#includeusingview codenamespace
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);}}
題解 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...