【题目来源】:https://cn.vjudge.net/problem/HDU-3336
【题意】
给出一个字符串,假设这个字符串长度为n,那么这个字符串的所有前缀字符串在原字符出现次数是多少。
举个例子:
s: “abab”
The prefixes are: “a”, “ab”, “aba”, “abab”
res=2+2+1+1=6。
【思路】
起初并没有想到用next数组去解决问题,而是想着是否可以暴力。。
大神们说可以动规,但是实力有限的我找不到对应的关系。所以只好作罢。
然后大神提醒我用next数组去解决问题。
忽然发现next数组表示的含义刚好可以用来解决这道题。
只要next数值不为0,不为-1,那么代表一定能够和前面匹配,既然能匹配,说明当前位置的字符串之前出现过,所以只要统计数值不为0和-1的次数,再加上最基础的n个字符串,什么是基础的呢?举个例子,假如字符串为ababa,那么基础的就是:
a
ab
aba
abab
ababa。
【代码】
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<limits.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int mod=1e9+7;
const double esp=1e-5;
typedef unsigned long long ll;
typedef long long LL;
char s[200000+10];
int nexx[200000+10];
int n;
void get_next()
{
int i=0,j;
j=nexx[0]=-1;
while(i<n)
{
while(-1!=j&&s[i]!=s[j]) j=nexx[j];
nexx[++i]=++j;
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
scanf("%s",s);
get_next();
int ans=0;
for(int i=1; i<=n; i++)
{
if(nexx[i]>0)
{
ans++;
if(ans>=10007)
ans-=10007;
}
}
ans+=n;
printf("%d\n",ans%10007);
}
}