在AC自动机上,目标节点建立xi = 1的方程,非目标节点建立xi = 0 的方程,其余节点根据Trie树Fail数组转移,建立 xi = ∑ aj * x[i->j] 然后sz个方程,sz个未知数,解得x0,即为从原始状态(游戏开始)到 第i人胜出的概率。 利用高斯消元解方程x0
代码
#include <bits/stdc++.h>
const long long mod = 1e9+7;
const double ex = 1e-10;
const int maxn = 205;
#define inf 0x3f3f3f3f
using namespace std;
int sgn(double x){
if (x > ex) return 1;
if ( x < -ex) return -1;
return 0;
}
struct Trie{
int ch[maxn][10];
int last[maxn];
int val[maxn];
int f[maxn];
double gauss[150][150];
int vis[150];
int now;
int sz;
Trie() {
sz = 1;
memset(ch[0],0,sizeof(ch[0]));
}
void init(){
sz = 1;
memset(ch,0,sizeof(ch));
memset(val,0,sizeof(val));
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));
}
void insert(int a[],int l,int v){
int u = 0;
for (int i = 0; i<l; i++){
int c = a[i];
if (!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = v;
}
void getFail(){
queue <int> q;
for (int c = 1;c<=6;c++){
int u = ch[0][c];
if (u){
f[u] = 0;
q.push(u);
last[u] = 0;
}
}
while (!q.empty()){
int r = q.front();q.pop();
for (int c = 1; c <=6 ; c++){
int u = ch[r][c];
if (!u){
ch[r][c] = ch[f[r]][c];continue;
}
q.push(u);
int v = f[r];
while (v && !ch[v][c]) v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
}
}
}
void dfs(int u){
vis[u] = 1;
gauss[u][u] = 1;
if (val[u]){
if (val[u] == now)
gauss[u][sz] = -1;
else
gauss[u][sz] = 0;
return;
}
for (int i = 1; i<=6 ;i++){
gauss[u][ch[u][i]] += -1.0/6.0;
if (!vis[ch[u][i]]) dfs(ch[u][i]);
}
}
double Gauss(){
int n = sz-1;
for (int i = n ; i >= 1; i--){ //enumerate the ith cancellation
int tmp;
for (tmp = i ; tmp >= 0; tmp--){
if (sgn(gauss[tmp][i]) != 0) break;
}
for (int j = 0 ; j <= tmp - 1 ; j++){
double x = - gauss[j][i]/gauss[tmp][i];
for (int t = 0 ; t <= sz ; t++)
gauss[j][t] = gauss[j][t] + x * gauss[tmp][t];
}
swap(gauss[tmp],gauss[i]);
}
return -gauss[0][sz]/gauss[0][0];
}
double getans(int x){
now = x;
memset(gauss,0,sizeof(gauss));
memset(vis,0,sizeof(vis));
dfs(0);
double ans = Gauss();
return ans;
}
}Tri;
int main()
{
int T;
cin >> T;
while (T--){
int N,L;
cin >> N >> L;
Tri.init();
for (int i = 1; i<=N; i++){
int a[20];
for (int j = 0 ; j<L ; j++){
cin >> a[j];
}
Tri.insert(a,L,i);
}
Tri.getFail();
for (int i = 1; i<=N; i++){
printf("%.6f%c",Tri.getans(i),i==N?'\n':' ');
}
}
return 0;
}
来源:https://www.cnblogs.com/HITLJR/p/7560161.html