題目鏈接
對於這個題,我們再利用KMP求出next數組後,可以有一下方法統計前綴字符出現的次數。
for (int i = 0; i <= na; i++) cnt[i] = 1;
for (int i = na; i >= 1; i--) cnt[nta[i]] += cnt[i];
第一個for,很好理解,就是前綴本身就算一個,那麼後一個for呢?
我們看樣例:
ABACABA
跑完兩個循環cnt數組:
4 2 2 1 1 1 1
我們手動模擬一下可知:
如果我們確定了第i個前綴cnt的值,那麼該應該累加到所有可以與該前綴匹配的點上。
所以就有:
cnt[nta[i]] += cnt[i]
講起來比較繞,自己手動模擬一邊就懂的差不多了。
下面是ac代碼:
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
typedef unsigned ll ull;
const int N = 1e6+5;
char a[N];
int nta[N];
int cnt[N];
int ansl[N], ansn[N];
int tot;
int main()
{
scanf("%s", a+1);
int na = strlen(a+1);
for (int i = 2, j = 0; i <= na; i++)
{
while(j > 0 && a[i] != a[j+1]) j = nta[j];
if (a[i] == a[j+1]) j++;
nta[i] = j;
}
for (int i = 0; i <= na; i++) cnt[i] = 1;
for (int i = na; i >= 1; i--) cnt[nta[i]] += cnt[i];
int gg = nta[na];
for (; gg != 0; gg = nta[gg])
{
ansl[tot] = gg;
tot++;
}
printf("%d\n", tot+1);
for (int i = tot-1; i >= 0; i--)
{
printf("%d %d\n", ansl[i], cnt[ansl[i]]);
}
printf("%d %d\n", na, 1);
return 0;
}