题目链接:Click here~~
题意:
给一个长为 n 的字符串 s,求出 s 的所有前缀能在原串中匹配的总次数。
解题思路:
直接考虑很难,所以换个角度,考虑在 s 的所有子串中前缀共出现了多少次。
令 dp[i] 表示子串 [0,i] 中前缀出现的次数,有 dp[i] = dp[ next[i] ] + 1。
Ps.写这道题才发现自己大一时写出的模板是错的,好开心啊!>.<
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
namespace Kmp
{
int f[N];
void get_fail(char *p)
{
f[0] = -1;
for(int i=1,j=-1;p[i];i++)
{
while(j != -1 && p[i] != p[j+1])
j = f[j];
if(p[i] == p[j+1])
j++;
f[i] = j;
}
}
void match(char *s,char *p)
{
//get_fail(p);
for(int i=0,j=-1;s[i];i++)
{
while(j != -1 && s[i] != p[j+1])
j = f[j];
if(s[i] == p[j+1])
{
if(p[++j + 1] == '\0') // s[i-j,i] matched !
{
}
}
}
}
}using namespace Kmp;
char p[N];
int dp[N];
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d%s",&n,p);
get_fail(p);
int ans = 0;
for(int i=0;i<n;i++)
{
dp[i+1] = dp[f[i] + 1] + 1;
ans = (ans + dp[i+1]) % 10007;
}
printf("%d\n",ans);
}
return 0;
}