BZOJ 3670 [Noi2014]動物園 (KMP next陣列應用)
3670: [Noi2014]動物園
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1271 Solved: 678
[Submit][Status][Discuss]
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
ab
abcababc
Sample Output
1
32
HINT
n≤5,L≤1,000,000
題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=3670
題目分析:get_next時預處理num陣列,這裡處理的是包含重複的,處理完再通過next陣列把重複的去掉即可,可是像註釋裡的那樣寫T了,其實很顯然那樣複雜度很高,最壞的情況接近len^2
#include <cstdio>
#include <cstring>
#define ll long long
int const MOD = 1e9 + 7;
int const MAX = 1e6 + 5;
char s[MAX];
int len, next[MAX], num[MAX];
ll ans;
void get_next()
{
ans = 1;
int i = 0, j = -1;
next[0] = -1;
while(s[i] != '\0')
{
if(j == -1 || s[i] == s[j])
{
i ++;
j ++;
next[i] = j;
num[i] = num[j] + 1;
/*
int k = j;
while(i < 2 * k)
k = next[k];
ans = (ll)((ans % MOD) * (num[k] % MOD + 1 % MOD) % MOD) % MOD;
*/
}
else
j = next[j];
}
i = 0, j = -1;
while(s[i] != '\0')
{
if(j == -1 || s[i] == s[j])
{
i ++;
j ++;
while(i < 2 * j)
j = next[j];
ans = (ll)((ans % MOD) * (num[j] % MOD + 1 % MOD) % MOD) % MOD;
}
else
j = next[j];
}
}
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
memset(num, 0, sizeof(num));
scanf("%s", s);
len = strlen(s);
get_next();
printf("%lld\n", ans);
}
}
相關文章
- bzoj3670: [Noi2014]動物園(kmp)KMP
- 關於 KMP next 陣列的應用KMP陣列
- KMP演算法的Next陣列詳解KMP演算法陣列
- KMP演算法next陣列的深入理解KMP演算法陣列
- KMP演算法以及優化(程式碼分析以及求解next陣列和nextval陣列)KMP演算法優化陣列
- KMP演算法的next、next value陣列的手工計算KMP演算法陣列
- KMP演算法中關於next陣列的探究KMP演算法陣列
- kmp 演算法簡介及 next 陣列推導KMP演算法陣列
- KMP演算法中我對獲取next陣列的理解KMP演算法陣列
- [資料結構]KMP演算法(含next陣列詳解)資料結構KMP演算法陣列
- KMP演算法的next、next value陣列程式碼實現及POJ3461KMP演算法陣列
- POJ 2406-Power Strings(重複子串-KMP中的next陣列)KMP陣列
- POJ 2752+KMP+利用next陣列性質求出所有相同的字首和字尾KMP陣列
- BZOJ2882: 工藝(字尾陣列)陣列
- RAID磁碟陣列應用AI陣列
- RAID 磁碟陣列的應用AI陣列
- 動態record陣列的應用陣列
- PHP 陣列current和next用法分享PHP陣列
- bzoj3155: Preprefix sum(樹狀陣列)陣列
- php陣列轉換js陣列操作及json_encode應用PHP陣列JSON
- VC++基礎 字串陣列的應用C++字串陣列
- 字元陣列的幾個應用函式字元陣列函式
- ORACLE 陣列在過程中的應用Oracle陣列
- 陣列可響應陣列
- 詳解JavaScript陣列特性與實踐應用JavaScript陣列
- 深度理解JavaScript陣列特性與實踐應用JavaScript陣列
- HarmonyOS NEXT應用開發案例—狀態列顯隱變化
- bzoj3289: Mato的檔案管理(莫隊+樹狀陣列)陣列
- 差分陣列原理與其字首和的應用陣列
- GO語言————7.6 字串、陣列和切片的應用Go字串陣列
- 給出分數陣列,得到對應的名次陣列陣列
- bzoj4500: 矩陣(dfs)矩陣
- bzoj2743: [HEOI2012]採花(樹狀陣列)陣列
- 資料結構:陣列,稀疏矩陣,矩陣的壓縮。應用:矩陣的轉置,矩陣相乘資料結構陣列矩陣
- Java陣列的運用Java陣列
- KMP演算法超詳解與其應用KMP演算法
- JavaScript中陣列的增刪改查以及應用方式JavaScript陣列
- C語言陣列應用例項2: 掃雷遊戲C語言陣列遊戲