ustbfym 2019-11-03
题目链接:https://vjudge.net/problem/HDU-3336
题意:给定长为n(<=2e5)的字符串s,求s的每个前缀在s中出现的次数之和。
思路:
用dp[i]表示以s[i]为结尾的子串是s的某一种前缀的方案数,那么dp[i]=dp[nex[i]]+1,因为[nex[i]-(i-nex[i])+1 , nex[i]] 和 [nex[i]+1 , i] 是一样的,所以计算后者时只用把前者+1即可(+1是因为以[1,i]为前缀的个数加一)。
AC代码:
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=2e5+5; const int MOD=1e4+7; int T,n,ans,nex[maxn],dp[maxn]; char s[maxn]; void get_next(){ int j; j=nex[0]=-1; for(int i=1;i<n;++i){ while(j>-1&&s[i]!=s[j+1]) j=nex[j]; if(s[i]==s[j+1]) ++j; nex[i]=j; } } int main(){ scanf("%d",&T); while(T--){ scanf("%d%s",&n,s); get_next(); ans=0; for(int i=1;i<=n;++i){ dp[i]=(dp[nex[i-1]+1]+1)%MOD; ans=(ans+dp[i])%MOD; } printf("%d\n",ans); } return 0; }