BZOJ 1444 有趣的游戏(AC自动机+矩阵快速幂)
真的是很有趣的游戏。。。
对每个单词构建好AC自动机后,由于单词都是相同长度的且不同,所以不会出现互相为子串的形式。
那么我们对AC自动机上的节点构建转移矩阵。对于每个单词末尾的节点。该节点的出边仅仅与自己相连且概率为1.
表示如果已经出现了该单词游戏就结束了。答案是收敛的,我们对这个矩阵迭代个2^50次应该就可以求出近似的答案了。
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi 3.1415926535 # define eps 1e-4 # define MOD 1000000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; inline int Scan() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=105; //Code begin... struct Matrix{double matrix[N][N];}sa; int trie[N][12], top, fail[N], m, pos[N]; char s[N]; double P[N]; void init(){top=1; mem(trie[0],0);} void ins(char *s, int i){ int rt, nxt; for (rt=0; *s; rt=nxt, ++s){ nxt=trie[rt][*s-'A']; if (!nxt) mem(trie[top],0), trie[rt][*s-'A']=nxt=top++; } ++trie[rt][10]; pos[i]=rt; } void makefail(){ int u, v, bg, ed; static int q[N]; fail[0]=bg=ed=0; FO(i,0,m) if ((v=trie[0][i])) fail[q[ed++]=v]=0; while (bg<ed){ u=q[bg++]; FO(i,0,m) { if ((v=trie[u][i])) fail[q[ed++]=v]=trie[fail[u]][i]; else trie[u][i]=trie[fail[u]][i]; } } } Matrix Mul(Matrix a, Matrix b) //矩阵乘法(%MOD) { Matrix c; FO(i,0,top) FO(j,0,top) { c.matrix[i][j]=0; FO(l,0,top) c.matrix[i][j]+=a.matrix[i][l]*b.matrix[l][j]; } return c; } int main () { int n, l, nxt; double x, y; scanf("%d%d%d",&n,&l,&m); init(); FO(i,0,m) scanf("%lf%lf",&x,&y), P[i]=x/y; FO(i,0,n) scanf("%s",s), ins(s,i); makefail(); FO(i,0,top) { if (trie[i][10]) {sa.matrix[i][i]=1; continue;} FO(j,0,m) nxt=trie[i][j], sa.matrix[i][nxt]+=P[j]; } FOR(i,1,50) sa=Mul(sa,sa); FO(i,0,n) printf("%.2f\n",sa.matrix[0][pos[i]]); return 0; }