Uva 11468 AC自动机或运算
AC自动机
UVa 11468
题意:给一些字符和各自出现的概率,在其中随机选择L次,形成长度为L的字符串S,给定K个模板串,求S不包含任意一个串的概率。
首先介绍改良版的AC自动机:
- 传统的AC自动机,是当一个字符失配时,根据失配函数转移到指定地方,而这个失配函数,是通过一个宽搜的过程形成的,这时在匹配串的时候,就当匹配失败时,顺着失配指针走,直到可以匹配。然后匹配到单词结点,或者后缀链接是一个单词结点,这些前面的结点也是匹配单词。这就是传统的AC自动机。
现在将这个AC自动机改版优化:
- 具体的变化是,计算失配指针的时候,当不存在某一个单词结点时,做一个虚结点,直接指向父亲结点的失配指针的位置,这样,当find查询匹配的时候,就不用判断当前结点是否存在,不存在则不断顺着失配边走。而是直接转到失配原来就预订好的位置。
- 对于此题:各个模板串构成一个AC自动机,题目就转为在这个自动机上走L步,不踩中单词结点的概率。这个概率可以用全概率公式计算,当前结点*下一步也成功的概率。
Source Code :
#include <bits/stdc++.h>
using namespace std; const int SIGMA_SIZE = ;
const int MAXNODE = ; int idx[];
char s[][];
double prob[SIGMA_SIZE];
int n; struct AhoCorasickAutomata
{
int ch[MAXNODE][SIGMA_SIZE];
int f[MAXNODE];
int match[MAXNODE];
int sz; void init()
{
sz = ;
memset(ch[],,sizeof(ch[]));
} void insert(char *s)
{
int u = ,n = strlen(s);
for(int i=; i<n; i++)
{
int c = idx[s[i]];
if(!ch[u][c])
{
memset(ch[sz],,sizeof(ch[sz]));
match[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
match[u] = ;
} void getFail()
{
queue<int> q;
f[] = ;
for(int c=; c<SIGMA_SIZE; c++)
{
int u = ch[][c];
if(u)
{
f[u] = ;
q.push(u);
}
} while(!q.empty())
{
int r = q.front();
q.pop();
for(int c=; c<SIGMA_SIZE; c++)
{
int u = ch[r][c];
if(!u)
{
ch[r][c]=ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while(v&&!ch[v][c])
v = f[v];
f[u] = ch[v][c];
match[u] |=match[f[u]];
}
}
}
}; AhoCorasickAutomata ac; double d[MAXNODE][];
int vis[MAXNODE][]; double getProb(int u,int l)
{
if(!l) return 1.0;
if(vis[u][l]) return d[u][l];
vis[u][l] = ;
double& ans = d[u][l];
ans = 0.0;
for(int i=; i<n; i++)
{
if(!ac.match[ac.ch[u][i]])
ans += prob[i]*getProb(ac.ch[u][i],l-);
}
return ans;
} int main()
{
freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
for(int kase = ; kase<=T; kase ++)
{
int k,l;
scanf("%d",&k);
for(int i=; i<k; i++)
scanf("%s",s[i]); scanf("%d",&n);
for(int i=; i<n; i++)
{
char ch[];
scanf("%s%lf",ch,&prob[i]);
idx[ch[]] = i;
} ac.init();
for(int i=; i<k; i++)
ac.insert(s[i]);
ac.getFail();
scanf("%d",&l);
memset(vis,,sizeof(vis));
printf("Case #%d: %.6lf\n",kase,getProb(,l));
} return ;
}
Uva 11468 AC自动机或运算的更多相关文章
- UVa 11468 (AC自动机 概率DP) Substring
将K个模板串构成一个AC自动机,那些能匹配到的单词节点都称之为禁止节点. 然后问题就变成了在Tire树上走L步且不经过禁止节点的概率. 根据全概率公式用记忆化搜索求解. #include <cs ...
- UVA - 11468 (AC自动机+动态规划)
建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...
- Substring UVA - 11468 AC自动机+概率DP
题意: 给出一些字符和各自对应的选择概率,随机选择L次后得到一个长度为L的随机字符串S. 给出K个模板串,计算S不包含任何一个模板串的概率 dp[i][j]表示走到AC自动机 i 这个节点 还需要走 ...
- UVA 11468 AC 自动机
首先我们应该是枚举 L个位置上的每个字符来得到最终概率 然后AC自动机的作用就是为了判断你枚举的地方是否对应了单词节点,如果对应了,就肯定要不得 #include <iostream> # ...
- UVA 11468 AC自动机入门题 记忆化概率dp+ac自动机
/** 链接:https://vjudge.net/problem/UVA-11468 详见lrj训练指南P218 我的是反向求存在模板串的概率. dp[i][j]表示当前i位置选择字符,前面i-1个 ...
- uva 11468 AC自动机+概率DP
#include<cstdio> #include<cstring> #include<queue> #include<cstdio> #include ...
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...
- AC自动机——Uva 11468 子串
题目链接:http://vjudge.net/contest/142513#problem/A 题意:给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L的随机字符串S.给出K个模版串, ...
- 沉迷AC自动机无法自拔之:[UVA 11468] Substring
图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...
随机推荐
- 软件测试作业——WordCount的测试
一.代码提交 1.代码地址:https://gitee.com/zst1978805482/WordCount 2.作业地址:https://edu.cnblogs.com/campus/xnsy/T ...
- encoding specified in XML prolog (UTF-8) is different from that specified in page directive (utf-8)
myeclipse下启动项目后出现错误:encoding specified in XML prolog (UTF-8) is different from that specified in pag ...
- MySQL主从复制,以及双机热备
MySQL数据库自身提供的主从复制功能可以方便的实现数据的多处自动备份,实现数据库的拓展.多个数据备份不仅可以加强数据的安全性,通过实现读写分离还能进一步提升数据库的负载性能. 下图就描述了一个多个数 ...
- c语言实现队列的基本操作
话不多说,直接代码 #include"stdio.h" #include"stdlib.h" typedef struct QNode{ int date; s ...
- 如何利用工具提高你的 Android 代码质量
在这篇文章中,我将通过不同的自动化工具如CheckStyle,FindBugs,PMD以及Android Lint来介绍(如何)提高你的安卓代码质量.通过自动化的方式检查你的代码非常有用,尤其当你在一 ...
- MySQL之基本语句
SQL是Structure Query language(结构化查询语言)的缩写,它是使用关系模型的数据库应用语言.在众多开源数据库中,MySQL正是其中最杰出的代表,MySQL是由三个瑞典人于20世 ...
- [转]Oracle ROWNUM用法和分页查询总结
本文转自:http://blog.csdn.net/fw0124/article/details/42737671 ****************************************** ...
- 【转载】BaseDao设计
BaseDao接口设计 1 import java.util.List; /** * Dao接口,定义Dao基本操作 由BaseDaoImpl实现 * @author wht * @param < ...
- C# 用tabcontrol实现窗体类似网页排版的显示
这里做的比较简陋,可以美化下 把form设置为非顶级控件,直接放在tabcontrol里边,然后实现tabcontrol的拖拽移除tabpage显示form以及添加tabpage mousemove的 ...
- flex布局的一些注意点
现在来总结下自己在项目中用flex布局的一些注意点 1.ui图中的布局方式与justify-content的布局方法不一样 这是就要利用flex-grow的空dom来分开子容器来达到页面布局的效果 2 ...