给出字符串S,S仅由a与b组成。有一个空串T,每次在末尾随机加上a或b。问期望几轮后S串为T串的后缀?
先用Kmp求出匹配失败去哪,然后可得状态转移。
f[i] = (sum[i-1] - sum[next[i] - 1] + f[i] + 1) * 0.5 + 0.5, f[0] = 2;
移项得 f[i] = sum[i-1] - sum[next[i] - 1] + 2。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define fi g[nx[i]][b[i+1]]
using namespace std;
typedef long long LL;
const int N = 45;
int T, n, nx[N], g[N][2];
bool b[N];
LL ans, f[N], sum[N];
char s[N];
void Next() {
g[0][b[1]] = 1;
Rep(i, 1, n) {
g[i][b[i+1]] = i + 1;
g[i][!b[i+1]] = g[nx[i]][!b[i+1]];
nx[i+1] = fi;
}
}
int main()
{
cin >> T;
while (T --) {
scanf ("%s", s+1);
n = strlen(s+1);
memset(nx, 0, sizeof(nx));
memset(g, 0, sizeof(g));
Rep(i, 1, n) b[i] = (s[i] == 'T');
memset(f, 0, sizeof(f));
Next();
f[0] = sum[0] = 2;
ans = 2;
Rep(i, 1, n-1) {
f[i] = sum[i-1] + 2;
if (g[i][!b[i+1]]) f[i] -= sum[g[i][!b[i+1]]-1];
sum[i] = sum[i-1] + f[i];
ans += f[i];
}
cout << ans << endl;
}
return 0;
}