题意: 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 }