Substring UVA - 11468 AC自动机加记忆化

OJ:https://vjudge.net/problem/UVA-11468

简单翻译:

给出一些字符和各自被选择的概率,随机选择L次之后,得到一个长度为L的随机字符串S,每次选择互相独立。给出K个模板串,计算S不包含任何一个模板串的概率,既S的任意一个子串都与K个模板串的任何一个相同

 

分析:

计算不包含模板串的概率,也就是要计算我们每次选择不会出现于模式串相同的子串的那些选择的概率之和。也就是全概率

对于每一次的随机选择,我们要保证的是,保证在选择当前字符之后,不会出现K个模式串中的那些串。怎么去保证这个过程呢?

这就要利用到AC自动机了,AC自动机是让我们来匹配字符串的,我们也可以使用其来确保不匹配。我们的每一次选择都相当于在AC自动机上移动了一步,也就是在AC自动机上的路径进行移动。

一个重要的点就是,我们不能在AC自动机上走到一个模版串的结束位置。

我们首先构造出AC自动机,当然这个AC自动机与我们传统的AC自动机来说是有一些不同的,稍后再说不同。

然后对于我们每一次的随机选择,都相当于在AC自动机中随机的走一步。我们每一次选择有给出的字符这些选择,对于每一种选择来说,有一些选择可能在AC自动机上可以继续往下走,但是有一些选择就会导致与当前AC自动机上的当前位置的下的任意一个点都不同,这时候当前路径就不能往下走了,我们就要往当前节点的fail节点走,因为在当前走的路径上出现了不匹配的情况,对于当前路径上的模式串,肯定就会不匹配,但是对于其他路径来说就不一定了,因为适配节点上匹配了部分相同的字符,所以就要走到其失配节点上,去保证之前走过的一些点继续走也不会到达一个模板串的结束位置。

另外一点就是,我们在当前路径上走,在当前路径上没有出现模板串的结束位置,但是这并不是说,在其他路径上就不会出现结束位置。比如这样两个串:abcd,bc。我们在abcd路径上走的时候,走到c字符时其实就已经在其他路径上出现了匹配的模式串。所以我们要保证对于我们在当前路径上走的每一个节点,我们要保证在该节点的失配节点上也不会出现模板串的结束位置。

满足了上面两点就可以了

 

代码实现:

#include 
#include 
#include 
#define MAX 450
#define N 80
#define L 101

typedef struct{
    int val[MAX];
    int word[MAX][80];
    int fail[MAX];
    int size;
}Trie;

int idx(char c);
void insert(char *s);
double dfs(int l,int index);
void getFail();
void push(int data);
int pop();
int isEmpty();
Trie trie;

char pattern[21][21];
double p[80];
double vis[L][MAX];
double d[L][MAX];
int queue[MAX],size,pre,next;

int main()
{
    int t;
    scanf("%d",&t);
    int cs = 1;
    for(;t>0;t--){
        trie.size = 1,size=0,pre=0,next=0;
        memset(trie.word[0],0,sizeof(trie.word[0]));
        memset(trie.val,0,sizeof(trie.val));
        memset(vis,0.0,sizeof(vis));
        memset(p,0.0,sizeof(p));
        int k,n,l;
        scanf("%d",&k);
        for(int i=0;i

 

你可能感兴趣的:(算法)