UVALive - 3490
Time Limit: 3000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
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(1T10) 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(1N26) 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
题意:
从空串开始,我们可以不断地从前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][n] = -m;
}
A[n-1][n-1] = 1;
A[n-1][n] = 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][n] -= A[j][n] * A[i][j];
}
A[i][n] /= 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;
}