标签:次方 code uva int script wap generator 自动 else
给定一个字符串 \(S\) 以及整数 \(n\),现在生成一个字符串 \(T\),每次可以等概率地随机选取大写字母的前 \(n\) 个并加到 \(T\) 的末尾。
当 \(T\) 中某个字串为 \(S\) 时停止该过程。
求 \(T\) 的期望长度。
多组数据,不超过 10 组。
先对给定串 \(S\) 建出一个状态转移图(即 Trie 图,可以直接使用构造 AC 自动机的算法)。
设 \(E(x)\) 为状态 \(x\) 到结束状态 \(F\) 的期望转移次数。
那么对于终状态 \(F\),显然 \(E(F) = 0\)。
对于其他状态 \(x\),则有 \(E(x) = \dfrac{1}{n} \sum\limits_{c= 1} ^n E(\delta(x, c)) + 1\),即所有下一个状态都需要走一步。
然后…… dp?不幸的是这并不是一个 DAG,是无法直接 dp 的。
不过我们可以根据这些式子构造出 \(|Q|\) (状态集大小)个一次方程,这样就可以使用 高斯消元 解出方程,答案即为 \(E(t_0)\)。
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
typedef vector<long double> vec;
typedef vector<vec> mat;
const int N = 17;
const int MaxS = 26;
long double gauss(mat x) {
int n = x.size();
for (register int i = 0; i < n; i++) {
int r = i;
while (r < n && !x[r][i]) ++r;
if (r != i) swap(x[r], x[i]);
for (register int j = i + 1; j < n; j++) {
ll f = x[j][i] / x[i][i];
for (register int k = i; k <= n; k++)
x[j][k] -= f * x[i][k];
}
}
for (register int i = n - 1; ~i; i--) {
for (register int j = i + 1; j < n; j++)
x[i][n] -= x[j][n] * x[i][j];
x[i][n] /= x[i][i];
}
return x[0][n];
}
int sigma;
struct DFA {
int ch[N][MaxS];
int fail[N], total;
void init(char* s) {
for (int x = 0; *s; s++) {
int c = *s - ‘A‘;
x = ch[x][c] = ++total;
}
queue<int> Q; Q.push(1);
while (!Q.empty()) {
int x = Q.front(); Q.pop();
for (register int c = 0; c < sigma; c++)
if (ch[x][c]) {
Q.push(ch[x][c]);
fail[ch[x][c]] = ch[fail[x]][c];
} else ch[x][c] = ch[fail[x]][c];
}
}
void reset() {
*this = DFA();
}
mat construct() {
int n = total;
mat E(n + 1, vec(n + 2));
for (register int i = 0; i < n; i++) {
E[i][i] += sigma;
for (register int j = 0; j < sigma; j++)
E[i][ch[i][j]] -= 1;
E[i][n + 1] = sigma;
}
E[n][n] = 1, E[n][n + 1] = 0;
return E;
}
} dfa;
char s[N];
void solve() {
scanf("%d%s", &sigma, s);
dfa.reset();
dfa.init(s);
mat E = dfa.construct();
printf("%lld\n", (long long)(gauss(E) + 0.5));
}
signed main() {
int T; cin >> T;
for (register int i = 1; i <= T; i++) {
printf("Case %d:\n", i);
solve();
if (T != i) puts("");
}
}
标签:次方 code uva int script wap generator 自动 else
原文地址:https://www.cnblogs.com/-Wallace-/p/13287285.html