您的位置:首页 > 其它

uva 11468 ac自动机+dp

2015-10-08 21:23 295 查看
题意:

求最后构成的长度为L的字符串不含有模式串的概率,没一个字符的概率已经给出来了。


思路:

自动机构造转移,然后dp[i][j]表示现在是第i步,在j这个状态。
转移方程就很好写了。


code:

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
double m[1000];
double dp[110][5110];
int Next[5010][63],fail[5010],End[5010];
struct Trie
{
int root,L;
int idx(char x){
if(x<='z' && x>='a') return x-'a';
if(x<='Z' && x>='A') return x-'A'+26;
if(x<='9' && x>='0') return x-'0'+52;
}
int newnode()
{
for(int i = 0;i < 62;i++)
Next[L][i] = -1;
End[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0;i < len;i++)
{
if(Next[now][idx(buf[i])] == -1)
Next[now][idx(buf[i])] = newnode();
now = Next[now][idx(buf[i])];
}
End[now] = 1;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0;i < 62;i++)
if(Next[root][i] == -1)
Next[root][i] = root;
else
{
fail[Next[root][i]] = root;
Q.push(Next[root][i]);
}
while( !Q.empty() )
{
int now = Q.front();
Q.pop();
End[now] |= End[fail[now]];
for(int i = 0;i < 62;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]);
}
}
}
void query(){
memset(dp, 0, sizeof(dp));
dp[0][root] = 1;
for(int i=0; i<=n; i++){
for(int j=0; j<L; j++){
for(int k=0; k<62; k++)
if(End[Next[j][k]] == 0)
dp[i+1][Next[j][k]] += dp[i][j]*m[k];
}
}
}
};
char tmp[40];
int T;
int main(){
Trie t;
cin>>T;
int icase = 0;
while(T--){
memset(m, 0, sizeof(m));
int k;
cin>>k;
t.init();
for(int i=1; i<=k; i++){
scanf("%s", tmp);
t.insert(tmp);
}
t.build();
cin>>n;
double tt;
for(int i=1; i<=n; i++){
scanf("%s %lf", tmp, &tt);
m[t.idx(tmp[0])] = tt;
}
cin>>n;
t.query();
double res = 0;
for(int i=0; i<t.L; i++)
res += dp
[i];
printf("Case #%d: %.6f\n", ++icase, res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  uva ac自动机