zoukankan      html  css  js  c++  java
  • bjoi 2011 禁忌 AC自动机+矩阵乘法

    题意: Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平。而后,Koishi恢复了读心的能力……

          

    如今,在John已经成为传说的时代,再次造访那座岛屿的人们却发现Koishi遇到了新麻烦。

           这次她遇到了Flandre Scarlet——她拥有可以使用禁忌魔法而不会受到伤害的能力。

           为了说明什么是禁忌魔法及其伤害,引入以下概念:

    1.字母集A上的每个非空字符串对应了一个魔法。

    其中A是包含了前alphabet个小写字母的集合。

    2.有一个集合T,包含了N个字母集A上的字符串

    T中的每一串称为一个禁忌串(Taboo string

    3.一个魔法,或等价地,其对应的串s因为包含禁忌而对使用者造成的伤害按以下方式确定:

               s分割成若干段,考虑其中是禁忌串的段的数目,不同的分割可能会有不同的数目,其最大值就是这个伤害。

          

    由于拥有了读心的能力,Koishi总是随机地使用Flandre Scarlet的魔法,可以确定的是,她的魔法正好对应字母集A上所有长度为len的串

    但是,Flandre Scarlet所使用的一些魔法是带有禁忌的,由于其自身特性,她可以使用禁忌魔法而不受到伤害,而Koishi就不同了。可怜的Koishi每一次使用对方的魔法都面临着受到禁忌伤害的威胁。

     

           你现在需要计算的是如果Koishi使用对方的每一个魔法的概率是均等的,那么每一次随机使用魔法所受到的禁忌伤害的期望值是多少。

     

    思路:AC自动机 经典题

    新建一个节点表示总概率

     

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 using namespace std;
      6 #define MAXN 100
      7 int n,len,m,top,node_num;
      8 char c[20];
      9 struct matrix
     10 {
     11     double a[MAXN][MAXN];
     12     matrix()
     13     {
     14         memset(a,0,sizeof(a));
     15     }
     16 };
     17 struct node
     18 {
     19     int name,id;
     20     bool end;
     21     node *next[30],*father,*failink;
     22     node()
     23     {
     24         end=0;
     25         memset(next,0,sizeof(next));
     26     }
     27 };
     28 matrix ans,G;
     29 node *head,memo[MAXN],*Q[MAXN];
     30 matrix operator *(const matrix &x,const matrix &y)
     31 {
     32     int i,j,k;
     33     matrix ans;
     34     for(i=0;i<=node_num;i++)
     35     for(j=0;j<=node_num;j++)
     36     for(k=0;k<=node_num;k++)
     37         ans.a[i][j]+=x.a[i][k]*y.a[k][j];
     38     return ans;
     39 }
     40 void insert(char c[])
     41 {
     42     int i,l=strlen(c),x;
     43     node *t=head,*p;
     44     for(i=0;i<l;i++)
     45     {
     46         x=c[i]-'a';
     47         if(t->next[x]==NULL)
     48         {
     49             p=&memo[top]; p->id=top++; p->name=x; t->next[x]=p; p->father=t;
     50         }
     51         t=t->next[x];
     52     }
     53     t->end=1;
     54 }
     55 void set_failure_link()
     56 {
     57     int left,right,i;
     58     node *t,*p;
     59     Q[left=right=1]=head;
     60     while(left<=right)
     61     {
     62         t=Q[left++];
     63         if(t->father==head) t->failink=head;
     64         else if(t!=head)
     65         {
     66             int x=t->name;
     67             p=t->father->failink;
     68             t->failink=p->next[x];
     69             if(p->next[x]->end==1) t->end=1;
     70         }
     71         for(i=0;i<m;i++)
     72         {
     73             if(t->next[i]!=NULL) Q[++right]=t->next[i];
     74             else 
     75             {
     76                 if(t==head) t->next[i]=head;
     77                 else t->next[i]=t->failink->next[i];
     78             }
     79         }
     80     }
     81 }
     82 void build_matrix()
     83 {
     84     node_num=top;
     85     int i,j;
     86     for(i=0;i<top;i++)
     87     if(memo[i].end!=1)
     88     {
     89         for(j=0;j<m;j++)
     90         {
     91             if(memo[i].next[j]->end==1)
     92             {
     93                 G.a[i][0]+=1/(double)m;G.a[i][top]+=1/(double)m;
     94             }
     95             else
     96             G.a[i][memo[i].next[j]->id]+=1/(double)m;
     97         }
     98     }
     99     G.a[top][top]=1;
    100 }
    101         
    102 double matrix_pow(int n)
    103 {
    104     int i,j;
    105     for(i=0;i<=node_num;i++) ans.a[i][i]=1;
    106     while(n>0)
    107     {
    108         if(n&1) ans=ans*G;
    109         G=G*G;
    110         n>>=1;
    111     }
    112     return ans.a[0][node_num];
    113 }
    114 int main()
    115 {
    116     freopen("taboo.in","r",stdin);
    117     freopen("taboo.out","w",stdout);
    118     memset(memo,0,sizeof(memo));
    119     scanf("%d%d%d",&n,&len,&m);
    120     int i,j;
    121     top=0;
    122     head=&memo[top]; head->id=top++;
    123     for(i=1;i<=n;i++)
    124     {
    125         scanf("%s",c);
    126         insert(c);
    127     }
    128     set_failure_link();
    129     build_matrix();
    130     printf("%lf\n",matrix_pow(len));
    131     return 0;
    132 }
  • 相关阅读:
    CF981D
    CF883H
    Hdu 5884
    全排列
    二叉搜索树实现
    my.ini配置详解
    主元素问题
    排序算法(还需补充)
    迷宫问题(DFS,BFS)
    算法导论4--求最大和数组
  • 原文地址:https://www.cnblogs.com/myoi/p/2481245.html
Copyright © 2011-2022 走看看