Description:
给出
n
n
个长度均为的不同
01
01
串,随机生成一个无限长的
01
01
串,对
n
n
个串中的每个,求出它最先在随机串中出现的概率.
Solution:
设
N
N
<script type="math/tex" id="MathJax-Element-432">N</script>为不为任意一个串的概率,那么考虑N后添加一个串A,但是可能中途生成B。那么我们计算这个概率,也就是A的前缀和B的后缀相等,相差的字符的概率,求和之后高斯消元即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 305;
int n, m;
long long h[maxn][maxn], bb[maxn];
char s[maxn][maxn], S[maxn];
double a[maxn][maxn], pw[maxn];
void gauss(int n) {
for(int i = 1; i <= n; ++i) {
int p = i;
for(int j = i + 1; j <= n; ++j) {
if(fabs(a[j][i]) > fabs(a[p][i])) {
p = j;
}
}
for(int j = 1; j <= n + 1; ++j) {
swap(a[i][j], a[p][j]);
}
double t = a[i][i];
for(int j = 1; j <= n + 1; ++j) {
a[i][j] /= t;
}
for(int j = 1; j <= n; ++j) {
if(j != i) {
double t = a[j][i];
for(int k = 1; k <= n + 1; ++k) {
a[j][k] -= a[i][k] * t;
}
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%s", s[i] + 1);
for(int j = 1; j <= m; ++j) {
h[i][j] = h[i][j - 1] * 19992147 + s[i][j];
}
}
pw[0] = 1;
bb[0] = 1;
for(int i = 1; i <= m; ++i) {
pw[i] = pw[i - 1] * 0.5;
bb[i] = bb[i - 1] * 19992147;
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
for(int k = 1; k <= m; ++k) {
if(h[i][k] == h[j][m] - h[j][m - k] * bb[k]) {
a[i][j] += pw[m - k];
}
}
}
a[i][n + 1] = -pw[m];
}
for(int i = 1; i <= n; ++i) {
a[n + 1][i] = 1;
}
a[n + 1][n + 2] = 1;
gauss(n + 1);
for(int i = 1; i <= n; ++i) {
printf("%.10f\n", a[i][n + 2]);
}
return 0;
}