【uva11468-Substring】AC自动机+dp
2016-07-19 22:01
309 查看
http://acm.hust.edu.cn/vjudge/problem/31655
题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板串的概率。
题解:
ed[i]标记trie上的点i是不是任意一个模板串的结尾(在求fail的时候ed[i]|=ed[i.fail])
d[i][l]表示从i出发还要走l步,构造的串不含模板串的概率,dp一下。注意清零。
题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板串的概率。
题解:
ed[i]标记trie上的点i是不是任意一个模板串的结尾(在求fail的时候ed[i]|=ed[i.fail])
d[i][l]表示从i出发还要走l步,构造的串不含模板串的概率,dp一下。注意清零。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; const int N=30,L=110,S=66; char s[L]; int cnt[N*L]; double d[N*L][L],pro[70]; bool ed[N*L]; queue<int> q; int num,k,n,l; struct node{ int son[70]; int fail; }a[N*L]; int idx(char c) { if(c<='z' && c>='a') return c-'a'+1; if(c<='Z' && c>='A') return c-'A'+27; return c-'0'+53; } void clear(int x) { a[x].fail=0; memset(a[x].son,0,sizeof(a[x].son)); } void trie(char *c) { int l=strlen(c); int x=0; for(int i=0;i<l;i++) { int t=idx(c[i]); if(!a[x].son[t]) { num++; clear(num); a[x].son[t]=num; } x=a[x].son[t]; } ed[x]=1; } void buildAC() { while(!q.empty()) q.pop(); for(int i=1;i<=S;i++) if(a[0].son[i]) q.push(a[0].son[i]); while(!q.empty()) { int x=q.front();q.pop(); int fail=a[x].fail; for(int i=1;i<=S;i++) { int y=a[x].son[i]; if(y) { a[y].fail=a[fail].son[i]; ed[y]|=ed[a[fail].son[i]]; q.push(y); } else a[x].son[i]=a[fail].son[i]; } } } double count(int x,int l) { if(l==0) return d[x][l]=1.0; if(d[x][l]!=-1) return d[x][l]; d[x][l]=0; for(int i=1;i<=S;i++) { if(!pro[i]) continue; int y=a[x].son[i]; if(!ed[y]) d[x][l]+=pro[i]*count(y,l-1); } return d[x][l]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T,cas=0; scanf("%d",&T); while(T--) { num=0; clear(0); memset(cnt,0,sizeof(cnt)); memset(ed,0,sizeof(ed)); memset(pro,0,sizeof(pro)); scanf("%d",&k); for(int i=1;i<=k;i++) { scanf("%s",s); trie(s); } buildAC(); scanf("%d",&n);getchar(); for(int i=1;i<=n;i++) { char c; scanf("%c",&c);getchar(); scanf("%lf",&pro[idx(c)]);getchar(); } scanf("%d",&l); for(int i=0;i<=num;i++) for(int j=0;j<=l;j++) d[i][j]=-1; printf("Case #%d: %lf\n",++cas,count(0,l)); } return 0; }
相关文章推荐
- C# 正则表达式的使用
- OO五大原则
- js实现文件上传—带进度条
- Qt 文件搜索(写入文本文件)
- NO7 创新
- Python学习进程(7)字符串
- 集合框架三迭代器(Iterator)
- leetcode解题笔记:146. LRU Cache
- 重学编程-编程入门指南 v1.4
- 求有环单链表的链表长
- Session
- 以写代学:python shutil模块
- 使用 log4j 打印日志
- 问题
- 求有环单链表的环连接点位置
- CentOS 7 VM下修改网卡名为eth0并启动问题解决
- android音乐播放器
- hdu5723 Abandoned country(最小生成树+任意点对距离)
- Django中Admin管理与权限管理(一)————模型创建
- Unity3d transform