题目大意
字符接大小为 c c c, T T T串初始为空,每次等概率往 T T T串后加一个字符,问 S S S串第一次是 T T T串的子串的期望长度
题解
设 c c c为字符集大小, n n n为 S S S的长度
设 G ( x ) = ∑ i = 0 P ( X > i ) x i , F ( x ) = ∑ i = 0 P ( X = i ) x i G(x)=\sum_{i=0}P(X>i)x^i,F(x)=\sum_{i=0}P(X=i)x^i G(x)=∑i=0P(X>i)xi,F(x)=∑i=0P(X=i)xi
已知 F ( 1 ) = 1 F(1)=1 F(1)=1,而 F ′ ( 1 ) F'(1) F′(1)即为所求
G ( x ) + F ( x ) = ∑ i = 0 P ( X ≥ i ) x i = x G ( x ) + 1 G(x)+F(x)=\sum_{i=0}P(X\ge i)x^i=xG(x)+1 G(x)+F(x)=i=0∑P(X≥i)xi=xG(x)+1
求导
G ′ ( x ) + F ′ ( x ) = x G ′ ( x ) + G ( x ) G'(x)+F'(x)=xG'(x)+G(x) G′(x)+F′(x)=xG′(x)+G(x)
代入 x = 1 x=1 x=1得
F ′ ( 1 ) = G ( 1 ) F'(1)=G(1) F′(1)=G(1)
所以求出 G ( 1 ) G(1) G(1)就行了
考虑直接用 G G G构造出 F F F,直接在后面加上一个 S S S,即 G ( x ) ( x c ) n G(x)(\frac{x}{c})^n G(x)(cx)n,但这显然是不对的,因为可能中途就已经出现了 S S S,继续分析,中途出现 S S S的地方只能是一个 b o r d e r border border
设 A i = [ S 1 , i = S n − i + 1 , n ] A_i=[S_{1,i}=S_{n-i+1,n}] Ai=[S1,i=Sn−i+1,n],就可以构造出 ∑ i = 1 n A i F ( x ) ( x c ) n − i \sum_{i=1}^{n}A_iF(x)(\frac{x}{c})^{n-i} ∑i=1nAiF(x)(cx)n−i,这个式子的含义与 G ( x ) ( x c ) n G(x)(\frac{x}{c})^n G(x)(cx)n是一样的,所以 ∑ i = 1 n A i F ( x ) ( x c ) n − i = G ( x ) ( x c ) n \sum_{i=1}^{n}A_iF(x)(\frac{x}{c})^{n-i}=G(x)(\frac{x}{c})^n ∑i=1nAiF(x)(cx)n−i=G(x)(cx)n
代入 x = 1 x=1 x=1
G ( 1 ) ( 1 c ) n = ∑ i = 1 n A i F ( 1 ) ( 1 c ) n − i G(1)(\frac{1}{c})^n=\sum_{i=1}^{n}A_iF(1)(\frac{1}{c})^{n-i} G(1)(c1)n=i=1∑nAiF(1)(c1)n−i
G ( 1 ) = ∑ i = 1 n A i c i G(1)=\sum_{i=1}^{n}A_ic^i G(1)=i=1∑nAici
code \text{code} code
#include<cstdio>
using namespace std;
const int N=1e5+100;
int c,T,n,s[N+10],kmp[N+10],a[N+10],Ans[5],Pow[N+10];
int main()
{
scanf("%d %d",&c,&T);
Pow[0]=1;for(int i=1;i<=N;i++) Pow[i]=Pow[i-1]*c%10000;
for(;T--;)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%s",&s[i]);
int j=0;
for(int i=2;i<=n;i++)
{
while(j&&s[j+1]!=s[i])
j=kmp[j];
if(s[j+1]==s[i]) j++;
kmp[i]=j;
}
int ans=0;
j=n;
while(j!=0) ans+=Pow[j],j=kmp[j];
for(int i=1;i<=4;i++) Ans[i]=ans%10,ans/=10;
for(int i=4;i>=1;i--) printf("%d",Ans[i]);
puts("");
}
return 0;
}