HDU 3336 Count the string(KMP+Next數組遞推)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3336

題目大意:給定一個字符串,求所有前綴串在母串中匹配的數量,包含前綴串本身。

注意一個坑點,雖然沒有被坑到。比如aaaaaa,前綴串aa的匹配數目爲4個。包括aaaaaa, aaaaaa, aaaaaa, aaaaaa

必須保證與前綴串匹配的串與之不交叉。


先求KMP的next數組,然後遍歷所有的前綴串,判斷這個前綴串中有幾個與匹配數。獲得的數目+前綴串總數就可以了。

爲了更好地說明問題,我們舉abcabcab爲例。首先result+=8(所有前綴串(包括本身));

ab 無

abc 無

abca 匹配串爲a,匹配數爲1   result++

abcab 匹配串爲ab,匹配數爲1 result++

abc abc 匹配串爲abc,匹配數爲1 result++


abcabca匹配串爲abca, 但是不滿足不交叉,即next[i] * 2 > i, 那麼就繼續對abca進行匹配,得到匹配串a。

所以有abcabca,因爲a1=a2, a2=a3,故a1=a3,這個自己感覺一下就可以了。至於中間的a之前已經作爲後綴子串計算過了。匹配數爲1, result++;


abcabcab 匹配串爲ab, 匹配數爲1, result++


這樣可以枚舉出所有的情況。不重複也不缺少,理由是每次枚舉的後綴子串的最後一位的下標都不一樣。

核心部分還是在next[i] * 2 > i時,應該計算出所有匹配的前綴後綴不交叉的匹配數目。


這個理解還得再看看這個例子:aaaa,匹配串爲aaa, 但是next[i] * 2 > i(交叉了),所以取aaa繼續操作,得到aa。aa與原串比不超過一半,所以aa aa是一組。但是因爲aa的next[2] > 0(很關鍵),所以繼續操作,得到a,a與原串比顯然不超過一半,所以aaaa也是一組。所以問題還是在於要一直處理到next <= 0爲止。


不懂提問吧,貼代碼來,網上的dp沒看明白啥意思,不過自己做出來感覺挺好,也挺快。

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
char str[200005];
int Next[200005];
void getNext(int len)
{
    int i = 0, j = -1;
    Next[0] = -1;
    while(i < len) {
        if(j == -1 || str[i] == str[j]) {
            Next[++i] = ++j;
        }
        else {
            j = Next[j];
        }
    }
}
int main ()
{
    int n, t;
    scanf("%d", &t);
    while (t --) {
        scanf("%d%s", &n, str);
        getNext(n);
        int sum = n, res;
        for (int i = 1; i <= n; i ++) {
            res = Next[i];
            while (res > 0) {
                if(res * 2 <= i) {
                    sum = (sum % 10007 + 1) % 10007;
                }
                res = Next[res];
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章