「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

UVA557 LA5578 Burger概率

UVA280 LA5588 VertexDFS

UVA557 LA5578 Burger概率

UVA763 LA5339 Fibinary Numbers大数