题意:
两个人分别拥有两个串P,Q,现在两个人玩掷硬币游戏,从一个空串开始,如果正面向上那么就在串后面+'1'否者+'0'。一旦这串中包含了P或者Q串就停止比赛,如果包含P则A赢,包含Q则B赢,否则平局。现在问A和B赢的概率分别是多少。
题解:
这题要分别对A赢和B赢进行dp,应为有平局的情况。那对于A赢dp,将P插入自动机标记为1,插入自动机标记-1,这样在建机时就将包含P和不包含Q的分开了!然后dp[i][j]表示掷硬币第i轮,走到自动机j节点对应的概率。对于B同理。
OJ问题ac不了。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> using namespace std; #define B(x) (1<<(x)) void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } typedef long long ll; const int oo=0x3f3f3f3f; const ll OO=1LL<<61; const int MOD=2012; const int maxn=55; const int SIZE=maxn*maxn*2; char P[maxn],Q[maxn]; double dp[maxn][SIZE]; struct AC_Autometon{ int next[SIZE][2],fail[SIZE],flag[SIZE]; int cnt,root; int newNode(){ for(int i=0;i<2;i++) next[cnt][i]=-1; flag[cnt]=0; return cnt++; } void Init(){ cnt=0; root=newNode(); } void Insert(char buff[],int id){ int now=root; for(int i=0;buff[i];i++){ int k=buff[i]-'0'; if(next[now][k]==-1) next[now][k]=newNode(); now=next[now][k]; } flag[now]=id; } void build(){ queue<int>q; int now=root; for(int i=0;i<2;i++){ if(next[now][i]==-1) next[now][i]=root; else{ fail[next[now][i]]=root; q.push(next[now][i]); } } while(!q.empty()){ now=q.front();q.pop(); if(flag[fail[now]]!=-1) flag[now]+=flag[fail[now]]; if(flag[fail[now]]==-1) flag[now]=-1; for(int i=0;i<2;i++){ if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else{ fail[next[now][i]]=next[fail[now]][i]; q.push(next[now][i]); } } } } double DP(int n){ memset(dp,0,sizeof dp); double ans=0; dp[0][0]=1; for(int i=0;i<n;i++){ for(int j=0;j<cnt;j++){ if(flag[j]!=0)continue; for(int t=0;t<2;t++){ int k=next[j][t]; if(flag[k]!=-1) dp[i+1][k]+=dp[i][j]*0.5; } } } for(int i=1;i<=n;i++){ for(int j=0;j<cnt;j++){ if(flag[j]>0) ans+=dp[i][j]; } } return ans; } void Debug(){ for(int i=0;i<cnt;i++){ printf("%d ch[ ",i); for(int j=0;j<2;j++) printf("%d ",next[i][j]); puts("]"); } } }ac; int main(){ //freopen("G:\\read.txt","r",stdin); int K,T; double ans1,ans2; scanf("%d",&T); while(T--){ scanf("%s%s",P,Q); scanf("%d",&K); ac.Init(); ac.Insert(P,1); ac.Insert(Q,-1); ac.build(); ans1=ac.DP(K); ac.Init(); ac.Insert(Q,1); ac.Insert(P,-1); ac.build(); ans2=ac.DP(K); printf("%.9lf %.9lf\n",ans1,ans2); } return 0; } /** 2 010 001 25 0 11 5 */