「UVA 1358」「LA 3490」Generator
Posted -wallace-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「UVA 1358」「LA 3490」Generator相关的知识,希望对你有一定的参考价值。
Description
给定一个字符串 (S) 以及整数 (n),现在生成一个字符串 (T),每次可以等概率地随机选取大写字母的前 (n) 个并加到 (T) 的末尾。
当 (T) 中某个字串为 (S) 时停止该过程。
求 (T) 的期望长度。
多组数据,不超过 10 组。
Hint
- (1le nle 26)
- (1le |S| le 15)
Solution
先对给定串 (S) 建出一个状态转移图(即 Trie 图,可以直接使用构造 AC 自动机的算法)。
设 (E(x)) 为状态 (x) 到结束状态 (F) 的期望转移次数。
那么对于终状态 (F),显然 (E(F) = 0)。
对于其他状态 (x),则有 (E(x) = dfrac{1}{n} sumlimits_{c= 1} ^n E(delta(x, c)) + 1),即所有下一个状态都需要走一步。
然后…… dp?不幸的是这并不是一个 DAG,是无法直接 dp 的。
不过我们可以根据这些式子构造出 (|Q|) (状态集大小)个一次方程,这样就可以使用 高斯消元 解出方程,答案即为 (E(t_0))。
Code
#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
", (long long)(gauss(E) + 0.5));
}
signed main() {
int T; cin >> T;
for (register int i = 1; i <= T; i++) {
printf("Case %d:
", i);
solve();
if (T != i) puts("");
}
}
以上是关于「UVA 1358」「LA 3490」Generator的主要内容,如果未能解决你的问题,请参考以下文章
javascript Genera un array que contiene la serie de fibonacci hastaelnúmeroindado
css genra un fondo personalizado al select asi es personalizado .. y en la parte de colors .. genera