簡體   English   中英

使用 Knuth Morris 計算每個前綴的出現次數

[英]Counting the number of occurrences of each prefix using Knuth Morris

我正在研究我的競爭性編碼技能,我遇到了一篇文章,用於計算字符串中每個前綴的出現次數。 這是問題陳述給定一個長度為 n 的字符串 s。 在問題的第一個變體中,我們要計算每個前綴 s[0…i] 在同一字符串中出現的次數。 在問題的第二個變體中,給出了另一個字符串 t,我們想要計算每個前綴 s[0…i] 在 t 中出現的次數。 我找到了解決辦法。

代碼:

for (int i = 0; i < n; i++)
    ans[pi[i]]++;
for (int i = n-1; i > 0; i--)
    ans[pi[i-1]] += ans[i];
for (int i = 0; i <= n; i++)
    ans[i]++;

據我所知,前綴是什么,我無法完全理解問題陳述:

例如:字符串:geekforgeek 有前綴 as:{g,ge,gee,geek,geekf,geekfo,geekfor,geekforg,geekforge,geekforgee} 作為正確的前綴。 有人可以幫我這個問題試圖計算什么,因為只有這些是出現一次的可用前綴。 提前致謝。

如果你到目前為止我假設你知道prefix_function。 所以我們考慮 string str = "ABACABA" 我們得到它的前綴數組 say pi as = {0, 0, 1, 0, 1, 2, 3} 來存儲所有正確前綴的出現(即我們不包括字符串本身) 我們創建一個長度為 str.length()+1 的新數組或向量(根據您的需要)'occ',其中 occ[i] 表示前綴 str[0:i] 的出現次數。

所以當你引用上面的代碼時,有三個循環。 首先,我必須解釋這些循環實際上在計算什么。 第一個循環很簡單,它只計算最長前綴的編號,它也是長度為 i 的字符串中的后綴。 對於前綴“A”,我們與 str[0:3] 和 str[0:5] 的前綴具有相同的后綴,如果仔細觀察,可以說“A”是最長的前綴,也是這兩個字符串的后綴,因此,我們從上面計算的數組 pi 中得到這個,因為它存儲了最長前綴的長度,它也是一個后綴。 同樣,對於前綴“AB”,我們將其作為最長的前綴和后綴在 str[1:6] 中,依此類推。 我們得到 occ = {3, 2, 1, 1, 0, 0, 0, 0}。 我希望第一個循環的想法很清楚。

現在,當我們考慮上面前綴“A”的示例時,如果我們觀察“ABACABA”,我們會看到在字符串 str[0:7] 中我們也有“A”作為后綴,但不是最長的前綴最長的地方== 后綴是“ABA”,所以在我們的第一個循環中,我們錯過了前綴的出現。 還假設如果我們有長度為 l 的前綴,它也是一個后綴並以索引 i 結束,並且為了得到一些長度為 l' < l 我們 go 為 pi[pi[i]-1] 或說 pi[l-1 ] 從前綴 function 可以清楚地看出。 因此,使用數組 pi 的這種方式,我們跟蹤在第一個循環中計算的長度小於的前綴。 如果我們知道長度前綴 i 恰好出現 occ[i] 次,那么這個數字必須添加到它的最長后綴(也是前綴)的出現次數上。

第三個循環是我們添加每個前綴的出現。 而在其他兩個中,我們只考慮后綴。

代碼應該是

 {  for (int i = 0; i < n; i++)
    ans[pi[i]]++;
for (int i = n-1; i > 0; i--)
    ans[pi[i]-1] += ans[i];     ///note the index
for (int i = 0; i <= n; i++)
    ans[i]++;
}

文章是https://cp-algorithms.web.app/string/prefix-function.html#counting-the-number-of-occurrences-of-each-prefix其中錯誤地提到了該索引。 如果我錯了,請糾正我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM