#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int M =211000;
char s[M];
int l;
int fail[M];
int dp[M]; //dp[i]:以s[i-1]结尾的子串的合法个数
//题意 : 求和所有前缀相同的子串个数
// 求s[i]为后缀 相同的前缀个数为 == s[next[i]]为后缀的个数 + 1
// 1为 1~s[i]这一个
void Get()
{
int i=0,k=-1;
fail[0]=-1;
while(i<l)
{
if(k==-1||s[i]==s[k])
{
fail[i+1]=k+1;
i++;
k++;
}
else
{
k=fail[k];
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>l;
scanf("%s",s);
Get();
dp[0]=0;
int ans=0;
for(int i=1;i<=l;i++)
{
if(fail[i]!=-1)
{
dp[i]=(dp[fail[i]]+1)%10007;
// fail[i]=k -> s1~sk-1==si-k+1~si-1 si-1==sk-1 以s[i-1]结尾的合法个数 等于s[k-1]结尾的合法个数+ 以1~i-1为前缀的这一个
ans=(ans+dp[i])%10007;
}
}
cout<<ans<<endl;
}
return 0;
}
hdu 3336 Kmp+dp
最新推荐文章于 2019-12-18 20:08:00 发布