題目鏈接: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;
}