您的位置:首页 > 其它

UVaLive 3490 - Generator (AC自动机 期望DP 高斯消元)

2014-10-05 20:16 633 查看
UVALive - 3490

Generator

Time Limit: 3000MSMemory Limit: Unknown64bit IO Format: %lld & %llu
[Submit]
[Go Back] [Status]

Description





We can generate a random string by generating a sequence of random characters and concatenating them together. Each character is chosen independently from the first n letters
in the English alphabet with equal probability. Only capital letters are used in this problem. The generation is stopped as soon as a specific pattern occurs in the random string.
Your task is to predict the expected length of the generated string.

Input

Standard input will contain multiple test cases. The first line of the input is a single integer T(1

T

10) which
is the number of test cases.T test cases follow, each preceded by a single blank line.
Each test case consists of a single integer N(1

N

26) which
is the number of letters used, and a pattern, which is a non-empty string consisting of letters chosen from the first N upper case English letters. The length of any pattern will not exceed 12.

Output

Results should be directed to standard output. Start each case with ``Case # : " on a single line, where # is the case number starting from 1. Two
consecutive cases should be separated by a single blank line. No blank line should be produced after the last test case.
For each test case, print the expected length of the generated random string.

Sample Input

5

2 A

2 ABA

3 AAAAA

26 ACMICPC

26 ZJUZJU


Sample Output

Case 1:
2

Case 2:
10

Case 3:
363

Case 4:
8031810176

Case 5:
308933352


Source

[Submit]
[Go Back] [Status]

题意:

从空串开始,我们可以不断地从前n个大写字母中随机选出字母,然后加到串的末尾,直到这个串包含一个给定的字符串时停止。求停止时字符串长度的期望。

构造出状态机,因为只有一个字符串,所以只有strlen(s)+1个节点

dp[i]表示i节点到达结束需要添加字符数期望

dp[i] =∑(dp[j] / m) + 1 j表示i添加一个字符c到达的节点。m表示可选字符数。

直接高斯消元解。

注意这题的精度问题,等式同时乘m,高斯消元的时候里面也要同时乘A[i][i]看代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 20;
typedef LL Matrix[20][20];

const int MAX_NODE = 20;
const int SIGMA_SIZE = 27;

char str[maxn];
Matrix MA;

struct ACAutomata {
int ch[MAX_NODE][SIGMA_SIZE];
bool val[MAX_NODE];
int f[MAX_NODE];
int sz;

void init() {
sz = 1; memset(ch[0], -1, sizeof(ch[0]));
val[0] = false;
}

int idx(char c) {
return c - 'A';
}

void insert(char * s) {
int n = strlen(s);
int u = 0;
for (int i=0; i<n; i++) {
int c = idx(s[i]);
if(-1 == ch[u][c]) {
memset(ch[sz], -1, sizeof(ch[sz]));
val[sz] = false;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = true;
}

void build() {
queue<int> Q;
f[0] = 0;
for (int i=0; i<SIGMA_SIZE; i++) {
int u = ch[0][i];
if(u != -1) { Q.push(u); f[u] = 0; }
else ch[0][i] = 0;
}
while (!Q.empty()) {
int u = Q.front(); Q.pop();
if(val[f[u]]) val[u] = true;
for (int c=0; c<SIGMA_SIZE; c++) {
int v = ch[u][c];
if(-1 != v) {
Q.push(v);
f[v] = ch[f[u]][c];
} else {
ch[u][c] = ch[f[u]][c];
}
}
}
}

void getMatrix(Matrix A, int n, int m) {
memset(A, 0, sizeof(A));
for(int i=0; i<n-1; i++) {
for(int j=0; j<m; j++) {
int to = ch[i][j];
A[i][to] += 1;
}
A[i][i] -= m;
A[i]
= -m;
}
A[n-1][n-1] = 1;
A[n-1]
= 0;
}
} ac;

void gauss(Matrix A, int n) {
int i, j, k, r;
for(i = 0; i < n; i++) {
r = i;
while(r < n && !A[r][i]) r++; // 这里用abs会很溢出
if(r != i) for(j = 0; j <= n; j++) swap(A[r][j], A[i][j]);
for(k = i+1; k < n; k++) if(A[k][i]) {
LL f = A[k][i]; // 这里乘了A[i]i]
for(j = i; j <= n; j++) {
A[k][j] = A[k][j] * A[i][i] - f * A[i][j];
}
}
}
for(i = n-1; i >= 0; i--) {
for(j = i+1; j < n; j++) {
A[i]
-= A[j]
* A[i][j];
}
A[i]
/= A[i][i];
}
}

int main() {
int T;

scanf("%d", &T);
for(int kase=1; kase<=T; kase++) {
int n;
if(kase > 1) putchar('\n');
scanf("%d%s", &n, str);
ac.init();
int len = strlen(str);
ac.insert(str);
ac.build();
memset(MA, 0, sizeof(MA));
int m = len + 1;
ac.getMatrix(MA, m, n);
gauss(MA, m);
LL ans = MA[0][m];
printf("Case %d:\n%lld\n", kase, ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: