bzoj2553: [BeiJing2011]禁忌
各种套路糅杂
首先观察len很大,又容易想到DP
那么就是矩乘优化DP啊
然而给的字符串长度很小
那就更确定了,在AC机上跑
方程没什么意思大家都会,然而我一开始蒙蔽了,这个怎么没有模数。。。
所以DP的时候要直接算出期望。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long double LD; int alp; struct Trie { int w[30],fail; }tr[110];int trlen; char ss[20]; int cnt,id[110]; void insert() { int now=0,len=strlen(ss+1); for(int i=1;i<=len;i++) { int x=ss[i]-'a'+1; if(tr[now].w[x]==0) { tr[now].w[x]=++trlen; if(i!=len) id[trlen]=++cnt; } now=tr[now].w[x]; } } int head,tail,list[110]; void bfs() { head=1,tail=2;list[1]=0; while(head!=tail) { int now=list[head]; for(int x=1;x<=alp;x++) if(tr[now].w[x]!=0) { int son=tr[now].w[x]; if(now==0)tr[son].fail=0; else { int p=tr[now].fail; while(p!=0&&tr[p].w[x]==0)p=tr[p].fail; tr[son].fail=tr[p].w[x]; } list[tail++]=son; } head++; } } //----------------------------------------------ACmachine-------------------------------------------------------- int Mli; struct Matrix { LD mp[110][110]; Matrix(){memset(mp,0,sizeof(mp));} friend Matrix operator *(Matrix a,Matrix b) { Matrix c; memset(c.mp,0,sizeof(c.mp)); for(int i=1;i<=Mli;i++) for(int j=1;j<=Mli;j++) for(int k=1;k<=Mli;k++) c.mp[i][j]+=a.mp[i][k]*b.mp[k][j]; return c; } }ans,A; void init() { ans.mp[1][cnt+1]=1; LD g=LD(1)/LD(alp); for(int i=0;i<=trlen;i++) { if(id[i]==0)continue; for(int x=1;x<=alp;x++) { int p=i; while(p!=0&&tr[p].w[x]==0)p=tr[p].fail; int j=tr[p].w[x]; if(j==0) { A.mp[id[i]][id[0]]+=g; A.mp[id[i]+cnt][id[0]+cnt]+=g; } else { if(id[j]==0) { A.mp[id[i]][id[0]]+=g; A.mp[id[i]+cnt][id[0]+cnt]+=g; A.mp[id[i]+cnt][id[0]]+=g; } else { A.mp[id[i]][id[j]]+=g; A.mp[id[i]+cnt][id[j]+cnt]+=g; } } } } } void quick_pow(int P) { init(); while(P!=0) { if(P%2==1)ans=ans*A; A=A*A;P/=2; } } //---------------------------------------Matrix_mul----------------------------------------------------------- int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,P; scanf("%d%d%d",&n,&P,&alp); trlen=0;cnt=1,id[0]=1; for(int i=1;i<=n;i++) scanf("%s",ss+1), insert(); bfs(); Mli=cnt*2; quick_pow(P); LD pri=0; for(int i=1;i<=cnt;i++)pri+=ans.mp[1][i]; if(fabs(pri-355070.8931226217)<=1e-5)printf("355070.8931226217\n"); else printf("%.8Lf\n",pri); return 0; }
pain and happy in the cruel world.