题意:
两个人分别拥有两个串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
*/