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自动机或运算的更多相关文章

  1. UVa 11468 (AC自动机 概率DP) Substring

    将K个模板串构成一个AC自动机,那些能匹配到的单词节点都称之为禁止节点. 然后问题就变成了在Tire树上走L步且不经过禁止节点的概率. 根据全概率公式用记忆化搜索求解. #include <cs ...

  2. UVA - 11468 (AC自动机+动态规划)

    建立AC自动机,把AC自动机当做一张图,在上面跑L个节点就行了. 参考了刘汝佳的代码,发现可能有一个潜在的Bug--如果模式串中出现了没有指定的字符,AC自动机可能会建立出错. 提供一组关于这个BUG ...

  3. Substring UVA - 11468 AC自动机+概率DP

    题意: 给出一些字符和各自对应的选择概率,随机选择L次后得到一个长度为L的随机字符串S. 给出K个模板串,计算S不包含任何一个模板串的概率 dp[i][j]表示走到AC自动机 i 这个节点 还需要走 ...

  4. UVA 11468 AC 自动机

    首先我们应该是枚举 L个位置上的每个字符来得到最终概率 然后AC自动机的作用就是为了判断你枚举的地方是否对应了单词节点,如果对应了,就肯定要不得 #include <iostream> # ...

  5. UVA 11468 AC自动机入门题 记忆化概率dp+ac自动机

    /** 链接:https://vjudge.net/problem/UVA-11468 详见lrj训练指南P218 我的是反向求存在模板串的概率. dp[i][j]表示当前i位置选择字符,前面i-1个 ...

  6. uva 11468 AC自动机+概率DP

    #include<cstdio> #include<cstring> #include<queue> #include<cstdio> #include ...

  7. UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

    就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...

  8. AC自动机——Uva 11468 子串

    题目链接:http://vjudge.net/contest/142513#problem/A 题意:给出一些字符和各自对应的选择概率,随机选择L次后将得到一个长度为L的随机字符串S.给出K个模版串, ...

  9. 沉迷AC自动机无法自拔之:[UVA 11468] Substring

    图片加载可能有点慢,请跳过题面先看题解,谢谢 这个鬼题目,上一波套路好了 先用题目给的模板串建\(AC\)自动机,把单词结尾标记为 \(val=1\),然后在建好的\(AC\)自动机上跑 \(dp\) ...

随机推荐

  1. UltraEdit 21.3 增加 mssql, json 高亮

    1.  %appdata%\IDMComp\UltraEdit 2.  将msql2k.uew,  json.uew 放到 wordfiles 目录即可 msql2k   json的uew 下载地址如 ...

  2. 问题记录——java.lang.IllegalArgumentException: Illegal character in scheme name at index 0

    以下http请求报错是因为,请求的地址前面有个空格.... 2019-01-09 03:30:23,154 ERROR [business.modules.merchantreportresult.s ...

  3. Angular4+NodeJs+MySQL 入门-02 MySql操作类

    NodeJs操作MySQL类 此类封装了几个常用的方法:插入,更新,删除,查询,开启事务,事务提交,事务回滚等操作.有一这个类,操作MYSQL就方便多了. 批处理,存储过程等方法还没有添加,因为觉得目 ...

  4. TimesTen启动停止命令

    ttDaemonAdmin –start 启动 ttDaemonAdmin –stop 停止 或打开服务cmd-serviers.msc,找到相关服务启动或停止.

  5. AQS的数据结构及实现原理

    接下来从实现角度来分析同步器是如何完成线程同步的.主要包括:同步队列.独占式同步状态获取与释放.共享式同步状态获取与释放以及超时获取同步状态等. 1.同步队列 同步器依赖内部的一个同步队列来完成同步状 ...

  6. newInstance和new的区别(good)

    从JVM 的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载.但是使用newInstance()方法的时候,就必须保证:1.这个 类已经加载:2.这个类已经连接了.而完成上面两个步骤 ...

  7. MyEclipse 中tomcat 调试时进入未打断点的代码

    在preferences里面取消挂起未捕获异常

  8. java.util.regex.Pattern正则表达式写验证器示例

    import java.util.regex.Pattern; /** * 校验器:利用正则表达式校验邮箱.手机号等 * */ public class Validator { /** * 正则表达式 ...

  9. MyBatis 中 sqlmapconfig核心标签typeAliases配置说明

    标签说明 在 MyBatis 的 sql 映射配置文件中,需要使用 paramterType.resultType 来设置 sql 语句的输入输出参数,一般参数都是基本的数据类型或封装类型,但都需要声 ...

  10. 互联网轻量级框架SSM-查缺补漏第一天

    简言:工欲其事必先利其器,作为一个大四的准毕业生,在实习期准备抽空补一下基础.SSM框架作为互联网的主流框架,在会使用的基础上还要了解其原理,我觉得会对未来的职场会有帮助的.我特意的买了一本<J ...