HDU 3336【前缀出现次数】dp+kmp
- 题意:求出字符串前缀出现的总次数,答案对1e4+7取模;
- 思路:我们先考虑kmp匹配前缀与自身,可惜是O(n*n)的复杂度,那么我们该怎样匹配呢?对于这样一个串,
- 我们可以很容易发现这样一件事cnt[s1]=cnt[s2]=cnt[s3]+1;我们初始化cnt[i]=1;然后从后往前累加cnt[nxt[i]]+=cnt[i],每出现一次长串,就会贡献自身的次数,为什么要倒着扫呢?因为长串对短串才有贡献。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e4+7;
char x[200100];
int nt[200100],m,cnt[200100];///cnt[i]代表长度为i的前缀出现次数
void kmp()
{
int i,j;
j=nt[0]=-1;
i=0;
while(i<m)
{
while(j!=-1 && x[i]!=x[j])
j=nt[j];
nt[++i]=++j;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cin>>m;
scanf("%s",x);
m=strlen(x);
kmp();
ll ans=0;
fill(cnt,cnt+m+1,1);
for(int i=m; i>=1; i--)
cnt[nt[i]]+=cnt[i];
for(int i=1; i<=m; i++)
(ans+=cnt[i])%=mod;
printf("%lld\n",ans);
}
}