ICPC 2005 hangzhou Generator (UVA1358)KMP + 期望DP / 高斯消元
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ICPC 2005 hangzhou Generator (UVA1358)KMP + 期望DP / 高斯消元相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
Generator
Weblink
https://www.luogu.com.cn/problem/UVA1358
Problem
给定一个字符串S和字符集大小n。要求另生成一个字符串,它一开始为空,每次平均且独立地随机生成一个字符集中的字符添加到其末尾,生成出字串S时停下,求所生成字符串的长度的期望。
显然生成的字符串越来越长,每次由 n n n 种字符选择,那么就有 i n i^n in 种方案数,杂乱无章的无从下手。所以从对答案的贡献角度出发,发现对于答案而言,有用的只有最后生成的字符串 T T T 的后缀与模式串 S S S 的匹配长度。因此很多杂乱的字符串实际上对于答案而言是同一种状态,即一共只有 0 ∼ L 0\\sim L 0∼L 种状态,表示两字符串匹配的长度。
这样就有了清晰的状态,考虑状态如何转移即可。
书中倒推由于都是未知的需要使用高斯消元解方程组,比较麻烦,精度还不能得到保障。我们这里利用一个小技巧,直接正推。利用 KMP , O ( n ) O(n) O(n) 求出失配数组 nex i , j \\text{nex}_{i,j} nexi,j(当然要在失配的时候用)
反过来设 f[i]
为从状态
0
0
0 到状态
i
i
i 期望次数,答案显然就是 f[len]
则可以把原转移方程直接改写为:
f
[
i
]
=
f
[
i
+
1
]
n
+
1
n
∑
j
=
0
n
−
1
f
[
nex
[
i
+
′
A
′
]
]
−
1
f[i] = \\frac{f[i+1]}{n}+\\frac{1}{n}\\sum_{j=0}^{n-1}{f[\\text{nex}[i + 'A\\ ']]} - 1
f[i]=nf[i+1]+n1j=0∑n−1f[nex[i+′A ′]]−1
就是
f
[
i
]
f[i]
f[i] 由下一步匹配成功的
f
[
i
+
1
]
f[i+1]
f[i+1] 与未匹配成功的
∑
j
=
0
n
−
1
f
[
nex
[
i
+
′
A
′
]
]
\\displaystyle \\sum_{j=0}^{n-1}{f[\\text{nex}[i + 'A\\ ']]}
j=0∑n−1f[nex[i+′A ′]] 减去一次期望操作转移而来。
化简成正推的形式即:
f
[
i
+
1
]
=
(
f
[
i
]
+
1
)
×
n
−
∑
j
=
0
n
−
1
f
[
nex
[
i
+
′
A
′
]
]
f[i+1] = (f[i] + 1)\\times n - \\sum_{j=0}^{n-1}{f[\\text{nex}[i + 'A\\ ']]}
f[i+1]=(f[i]+1)×n−j=0∑n−1f[nex[i+′A ′]]
初始化 f[0] = 0
,然后
O
(
n
)
O(n)
O(n) 正序递推即可。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 50;
int n, m, k, t, ans, kcase, cases;
int a[N];
int nex[N];
char s[N];
ll f[N];
int len;
void get_nex(char* s)
{
for (int i = 2, j = 0; i <= len; ++ i) {
while(j != 0 && s[j + 1] != s[i])
j = nex[j];
if(s[j + 1] == s[i])
++ j;
nex[i] = j;
}
}
void solve()
{
scanf("%d%s", &n, s + 1);
len = strlen(s + 1);
get_nex(s);
f[0] = 0;
for (int i =0; i <= len - 1; ++ i) {
f[i + 1] = (f[i] + 1) * n;
for (int j = 0; j < n; ++ j) {
if(s[i + 1] == 'A' + j)
continue;
int pos = i;
while(pos && s[pos + 1] != j + 'A')
pos = nex[pos];
if(s[pos + 1] == j + 'A')
++ pos;
f[i + 1] -= f[pos];
}
}
printf("%lld\\n", f[len]);
}
int main()
{
scanf("%d", &t);
while(t -- ) {
printf("Case %d:\\n", ++ kcase);
solve();
if(t)
puts("");
}
return 0;
}
以上是关于ICPC 2005 hangzhou Generator (UVA1358)KMP + 期望DP / 高斯消元的主要内容,如果未能解决你的问题,请参考以下文章
习题3-1 得分(Score, ACM/ICPC Seoul 2005, UVa1585)
紫书例题3-5 生成元(Digit Generator, ACM/ICPC Seoul 2005, UVa1583)
2004-2005 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2004)
ACM-ICPC SouthWestern Europe Regional Contest 2017题解
computer repair services in Hangzhou
javascript Genera un array que contiene la serie de fibonacci hastaelnúmeroindado