【bzoj1444】【jsoi2009】【有趣的遊戲】【AC自動機+矩陣乘法】

Description

Input

注意 是0<=P

Output

Sample Input


Sample Output


HINT

 30%的數據保證, n ≤ 2. 50%的數據保證, n ≤ 5. 100%的數據保證, n , l, m≤ 10.

題解:

         對所有玩家的串建立AC自動機.

         對於非單詞節點,我們按概率轉移到其他點.

         對於單詞節點我們向它自己連一條概率爲1的邊.

         這樣既可以累加答案有保證了不會從單詞節點向外轉移.

         這樣就算出了在AC自動機上的轉移矩陣a.

         對於第i個串,它在AC自動機上結束的位置是pos[i]

         那第i個串的答案就是a[1][pos[i]]的值.

         將轉移矩陣自乘上幾十遍就可以保證精度.

代碼:

       

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200
using namespace std;
int a[N][30],cnt=1,x,y,n,l,m,q[N],fail[N],pos[N],id[N];
char ch[N];
double p[N];
int read(){
  int x(0);char ch=getchar();
  while (ch<'0'||ch>'9') ch=getchar();
  while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
  return x;
}
struct use{
  double a[N][N];
  use(){memset(a,0,sizeof(a));}
  friend use operator*(use a,use b){
    use ans;
    for (int i=1;i<=cnt;i++)
     for (int j=1;j<=cnt;j++)
      for (int k=1;k<=cnt;k++)
        ans.a[i][j]+=a.a[i][k]*b.a[k][j];
    return ans;
  }
}c;
void insert(int x){
  int len=strlen(ch),now=1;
  for (int i=0;i<len;i++){
    int u=ch[i]-'A'+1;
    if (a[now][u]) now=a[now][u];
    else a[now][u]=++cnt,now=a[now][u];
  }
  pos[now]=1;id[x]=now;
}
void getfail(){
  int h(0),t(1);
  q[0]=1;fail[1]=0;
  while (h<t){
    int u=q[h++];
    for (int i=1;i<=m;i++){
      if (!a[u][i]) continue;
      int k=fail[u];
      while (!a[k][i]) k=fail[k];
      fail[a[u][i]]=a[k][i];
      if (pos[a[k][i]]) pos[a[u][i]]=1;
      q[t++]=a[u][i];
    }
  }
}
void getmatrix(){
  //cout<<a[1][2]<<endl;
  for (int i=1;i<=cnt;i++) 
    if (pos[i]) c.a[i][i]=1;
    else{
     for (int j=1;j<=m;j++){
       int u=i;
       while (!a[u][j]) u=fail[u];
       u=a[u][j];
       c.a[i][u]+=p[j]; 
      }
    }
}
int main(){
  //freopen("a.in","r",stdin);
  n=read();l=read();m=read();
  for (int i=1;i<=m;i++){
    x=read();y=read();
    p[i]=(double)x/(double)y; 
  }
  for (int i=1;i<=26;i++) a[0][i]=1; 
  for (int i=1;i<=n;i++){
    scanf("%s",ch);
    insert(i);  
  }
  getfail();
  getmatrix();
  /*for (int i=1;i<=cnt;i++){
    for (int j=1;j<=cnt;j++)
      cout<<c.a[i][j]<<' ';
    cout<<endl;
  }*/
  for (int i=1;i<=50;i++) c=c*c;
  for (int i=1;i<=n;i++) printf("%.2lf\n",c.a[1][id[i]]);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章