【JSOI2009】有趣的游戏

题面

http://darkbzoj.tk/problem/1444

题解

#include<iostream>
#include<cstdio>
#include<queue>
#define ri register int
using namespace std;
struct node{
  int son[26],fail,last;
} t[500];
int tot,n,m,l,pos[20];
char ch[50];
double g[200][200],p[50];

void insert(char *s,int id) {
  int u=0;
  for (ri i=1;i<=l;i++) {
    if (!t[u].son[s[i]-65]) t[u].son[s[i]-65]=++tot;
    u=t[u].son[s[i]-65];
  }
  t[u].last=id; pos[id]=u;
}

void build() {
  queue<int> q;
  for (ri i=0;i<m;i++) if (t[0].son[i]) q.push(t[0].son[i]);
  while (!q.empty()) {
    int u=q.front(); q.pop();
    for (ri i=0;i<m;i++) {
      if (t[u].son[i]) t[t[u].son[i]].fail=t[t[u].fail].son[i],q.push(t[u].son[i]);
      else t[u].son[i]=t[t[u].fail].son[i];
      t[u].last|=t[t[u].fail].last;
    }
  }
}

void Gauss() {
  for (ri i=0;i<=tot;i++) {
    int p=0;
    for (ri j=i;j<=tot;j++) if (g[j][i]) {p=j;break;}
    for (ri j=0;j<=tot+1;j++) swap(g[i][j],g[p][j]);
    double t=g[i][i];
    for (ri j=0;j<=tot+1;j++) g[i][j]/=t;
    for (ri j=i+1;j<=tot;j++) {
      double d=g[j][i];
      for (ri k=0;k<=tot+1;++k) g[j][k]-=g[i][k]*d;
    }
  }
  for (ri i=tot;i>=0;i--) {
    g[i][tot+1]/=g[i][i];
    for (ri j=i-1;j>=0;j--) g[j][tot+1]-=g[j][i]*g[i][tot+1];
    if (!g[i][tot+1]) g[i][tot+1]=0;
  }
}

int main(){
  scanf("%d %d %d",&n,&l,&m);
  for (ri i=0;i<m;i++) {
    int a,b;
    scanf("%d %d",&a,&b);
    p[i]=1.0*a/b;
  }
  for (ri i=1;i<=n;i++) {
    scanf("%s",ch+1);
    insert(ch,i);
  }
  build();
  for (ri i=0;i<=tot;i++) 
    for (ri j=0;j<m;j++) if (!t[i].last) g[t[i].son[j]][i]+=p[j];
  for (ri i=0;i<=tot;i++) g[i][i]--;
  for (ri i=0;i<=tot;i++) if (t[i].last) g[0][i]=1; else g[0][i]=0;
  g[0][tot+1]=1;
  Gauss();
  for (ri i=1;i<=n;i++) printf("%.2lf\n",g[pos[i]][tot+1]);
}

猜你喜欢

转载自www.cnblogs.com/shxnb666/p/11279464.html