[CTSC2006] 歌唱王国(概率生成函数 + KMP / 哈希)

文章目录

题面

洛谷P4548 [CTSC2006]歌唱王国

分析

先了解一下概率生成函数,对于一个随机变量 a a a,它的概率生成函数是 F ( x ) = ∑ i ≥ 0 ( Pr ( a = i ) ⋅ x i ) F(x)=\sum\limits_{i\geq0}(\text{Pr}(a=i)\cdot x^i) F(x)=i0(Pr(a=i)xi)对它求导得 F ′ ( x ) = ∑ i ≥ 0 ( Pr ( a = i ) ⋅ i ⋅ x i − 1 ) F'(x)=\sum\limits_{i\geq0}(\text{Pr}(a=i)\cdot i\cdot x^{i-1}) F(x)=i0(Pr(a=i)ixi1)根据期望的定义可得 E ( a ) = F ′ ( 1 ) \mathbb{E}(a)=F'(1) E(a)=F(1)


那么对于这道题,设 f i f_i fi表示,长度为 i i i的串结束(找到匹配)的概率, g i g_i gi表示长度为 i i i的串未结束(还没找到匹配)的概率。 f 0 = 0 f_0=0 f0=0 g 0 = 1 g_0=1 g0=1
对随机变量 a 1 : = a_1:= a1:=结束时的长度 和随机变量 a 2 : = a_2:= a2:=未结束时的长度 分别定义概率生成函数: F ( x ) = ∑ i ≥ 0 ( f i ⋅ x i ) F(x)=\sum\limits_{i\geq0}(f_i\cdot {x}^i) F(x)=i0(fixi) G ( x ) = ∑ i ≥ 0 ( g i ⋅ x i ) G(x)=\sum\limits_{i\geq0}(g_i\cdot {x}^i) G(x)=i0(gixi)可知题目要求的是 E ( a 1 ) = F ′ ( 1 ) \mathbb{E}(a_1)=F'(1) E(a1)=F(1)


为什么要定义 g g g,当然是因为只定义 f f f不好算,定义了 g g g过后,我们能写 g g g的转移式: g i = f i + 1 + g i + 1 g_i=f_{i+1}+g_{i+1} gi=fi+1+gi+1相当于往长度为 i i i的串后面加一个字符,看能否结束,根据加法原理将两个概率相加。

于是有 F ( x ) + G ( x ) = ∑ i ≥ 0 [ ( f i + g i ) ⋅ x i ] = ∑ i ≥ 1 ( g i − 1 ⋅ x i ) + 1 = ∑ i ≥ 0 ( g i ⋅ x i + 1 ) + 1 = G ( x ) ⋅ x + 1 \begin{aligned} F(x)+G(x)&=\sum\limits_{i\geq0}\left[(f_i+g_i)\cdot x^i\right]\\ &=\sum\limits_{i\geq1}(g_{i-1}\cdot x^i)+1\\ &=\sum\limits_{i\geq0}(g_{i}\cdot x^{i+1})+1\\ &=G(x)\cdot x+1 \end{aligned} F(x)+G(x)=i0[(fi+gi)xi]=i1(gi1xi)+1=i0(gixi+1)+1=G(x)x+1两边同时求导得 F ′ ( x ) + G ′ ( x ) = G ′ ( x ) ⋅ x + G ( x ) F'(x)+G'(x)=G'(x)\cdot x+G(x) F(x)+G(x)=G(x)x+G(x)于是 E ( x ) = F ′ ( 1 ) = G ( 1 ) \mathbb{E}(x)=F'(1)=G(1) E(x)=F(1)=G(1)


接下来就要考虑 G ( 1 ) G(1) G(1)怎么算了。直觉告诉我们,两个变量得两个方程,所以还需要找到一个本质不同的 g g g f f f的关系,这个时候肯定得跟原串(牛人酋长的名字) A A A扯上关系。既然 g i g_i gi是没有结束的概率,那么我们强制让它结束掉,不就和 f f f扯上关系了么。设字符集大小为 n n n A A A的长度为 L L L。考虑把 A A A强制接在 g i g_i gi对应的某个串后面: g i ⋅ ( 1 n ) L = ∑ A [ 1 , ⋯   , d ] = A [ L − d + 1 , ⋯   , L ] f i + d ⋅ ( 1 n ) L − d g_i\cdot\left(\dfrac{1}{n}\right)^L=\sum\limits_{A[1,\cdots,d]=A[L-d+1,\cdots,L]}f_{i+d}\cdot\left(\dfrac{1}{n}\right)^{L-d} gi(n1)L=A[1,,d]=A[Ld+1,,L]fi+d(n1)Ld

图示
如图对应了一种 f i + d ⋅ ( 1 n ) L − d f_{i+d}\cdot\left(\dfrac{1}{n}\right)^{L-d} fi+d(n1)Ld的情况,即阴影部分相等。对于 g i g_i gi,强制规定上方的橙色部分,对于 f i + d f_{i+d} fi+d,强制规定白色方框部分。由于下方的橙色部分可以移动,所以对所有border的情况求和。

r i = [ A [ 1 , ⋯   , d ] = A [ L − d + 1 , ⋯   , L ] ] r_i={\large[}A[1,\cdots,d]=A[L-d+1,\cdots,L]{\large]} ri=[A[1,,d]=A[Ld+1,,L]],根据上式就有 G ( x ) ⋅ ( 1 n ) L ⋅ x L = ∑ 1 ≤ i ≤ L ( r i ⋅ F ( x ) ⋅ x L − i ) G(x)\cdot\left(\dfrac{1}{n}\right)^L\cdot x^L=\sum\limits_{1\leq i\leq L}\left(r_i\cdot F(x)\cdot x^{L-i}\right) G(x)(n1)LxL=1iL(riF(x)xLi)这个式子我只能暴力证明它是对的:怎么来的就只能感性认知了 证明


于是得到 G ( 1 ) ⋅ ( 1 n ) L = F ( 1 ) ⋅ ∑ 1 ≤ i ≤ L ( r i ⋅ n i − L ) G(1)\cdot\left(\dfrac{1}{n}\right)^L=F(1)\cdot \sum\limits_{1\leq i\leq L}(r_i\cdot n^{i-L}) G(1)(n1)L=F(1)1iL(riniL)注意 F ( 1 ) = ∑ i ≥ 0 f i = 1 F(1)=\sum\limits_{i\geq0}f_i=1 F(1)=i0fi=1,因为无论怎样必定有一个时刻会结束,所以 E ( a 1 ) = G ( 1 ) = ∑ 1 ≤ i ≤ L ( r i ⋅ n i ) \mathbb{E}(a_1)=G(1)=\sum\limits_{1\leq i\leq L}(r_i\cdot n^i) E(a1)=G(1)=1iL(rini)哈希或者KMP处理border( r i r_i ri),结束。

代码

#include <algorithm>
#include <cstdio>
#include <cstring>

const int MAXN = 100000;
const int MOD = 10000;

int Pow(int x, int y) {
	int ret = 1;
	while (y) {
		if (y & 1)
			ret = ret * x % MOD;
		y >>= 1;
		x = x * x % MOD;
	}
	return ret;
}

int N, L;
int S[MAXN + 5], Fail[MAXN + 5];

int main() {
	int T, N;
	scanf("%d%d", &N, &T);
	N %= MOD;
	while (T--) {
		scanf("%d", &L);
		memset(Fail, 0, sizeof Fail);
		for (int i = 1; i <= L; i++)
			scanf("%d", &S[i]);
		for (int i = 2; i <= L; i++) {
			int k = Fail[i - 1];
			while (k && S[k + 1] != S[i])
				k = Fail[k];
			if (S[k + 1] == S[i])
				Fail[i] = k + 1;
		}
		int Ans = 0;
		for (int i = L; i; i = Fail[i])
			Ans = (Ans + Pow(N, i)) % MOD;
		printf("%04d\n", Ans);
	}
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值