您的位置:首页 > 其它

uva 11468-Substring ac自动机 + 记忆化搜索

2015-08-31 15:28 232 查看
题目大意:给定k个模式串,然后给定在每一步中字母被选中的概率,求获得长度为L的字符串的且其中不包含任何模式串的概率是多少。

 此题既然给定的是模式串,我们首先想到肯定是要建立自动机,但是建立自动机之后该怎么办呢?

这里就要思考,符合题意的串到底该如何求得呢?

ac自动机说道底就是状态的转换。在构造串时就是没每一步选择一个字符,一旦选择了这个字符,那么现在的串的任何后缀不能是任何模式串。因为如果某个后缀是某个模式串,那么肯定不符合题意啊。所以,此题就是在当前字符串在的ac自动机的那个状态上,选择下一个字母,且满足选择的下一个字母与当前字符串组合之后的字符串的任何后缀不是某个模式串。到此使用的算法也就是搜索,以ac自动的状态为当前节点,遍历下一个可以取的字符。同时加个记忆化。

//
// main.cpp
// uva 11468 SubString---AC自动机
//
// Created by XD on 15/8/31.
// Copyright (c) 2015年 XD. All rights reserved.
//
//ac自动机 + 加记忆化搜索

#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
const int maxn =410 ;
const int sigma_size = 65 ;
double prob[65 ] ;
struct Ahocrosickautomata
{
int ch[maxn][sigma_size] ;
int sz , f[maxn] , match[maxn] ;
void init()
{
sz = 1 ;
memset(ch[0], 0, sizeof(ch[0])) ;
match[0] =0 ;
}
int idx(char ch)
{
if(ch >='A'&& ch<='Z') return ch-'A' ;
else if (ch >='a'&&ch <= 'z') return ch - 'a' + 26;
else return ch - '0' + 52 ;
}
void insert(char *s,int v)
{
int u = 0 ;
int len = (int)strlen(s) ;
for(int i = 0 ; i < len ; i++)
{
int j = idx(s[i] );
if(!ch[u][j])
{
memset(ch[sz], 0, sizeof(ch[sz])) ;
match[sz] = 0 ;
ch[u][j] = sz++ ;

}
u = ch[u][j] ;
}
match[u] = v ;
}
void getFail()
{
f[0] = 0 ;
queue<int > q ;
for(int i = 0 ; i < sigma_size ; i++)
{
int u =ch[0][i] ;
if(u) {f[u] =0 ; q.push(u) ; }

}
while(!q.empty())
{
int r = q.front() ;q.pop() ;
for(int i = 0 ; i < sigma_size ;i++)
{
int u =ch[r][i] ;
if(!u) {ch[r][i] = ch[f[r]][i] ; continue;}
q.push(u) ;
int v = f[r] ;
while(v && !ch[v][i]) v = f[v] ;
f[u] =ch[v][i] ;
match[u] |= match[f[u]] ;
}
}
}

};
Ahocrosickautomata ac ;
int vis[maxn][110] ;
double d[maxn][110] ;
vector<char> alph ;
double getProb(int u ,int L)
{
if (!L) {
return 1.0 ;
}
if(vis[u][L]) return d[u][L] ;
vis[u][L] = 1 ;
double ans = 0 ; d[u][L] = 0 ;
int len =(int )alph.size() ;
for (int i = 0 ; i < len ; i++) {
int v = ac.ch[u][ac.idx(alph[i])] ;
if (!ac.match[v]) {
ans += prob[ac.idx(alph[i])] * getProb(v, L-1) ;
}
}
d[u][L] = ans ;
return ans ;
}
int main(int argc, const char * argv[]) {
int T ; scanf("%d" ,&T) ;
char c ;int kase = 0,L ;
char s[25] ;
while (T--) {
alph.clear() ;
ac.init() ;
int k,n ;
scanf("%d" ,&k) ;
for (int i = 0 ; i < k ; i++) {
scanf("%s" ,s) ;
ac.insert(s, 1) ;
}
ac.getFail() ;
scanf("%d" ,&n) ;
for (int i = 0 ; i < n ; i++) {
// scanf(" %c%lf" ,&c , &prob[ac.idx(c)]) ;
getchar() ;
scanf("%c" , &c) ;
scanf("%lf" ,&prob[ac.idx(c)]) ;
alph.push_back(c) ;
}
memset(vis, 0, sizeof(vis)) ;

scanf("%d" , &L) ;
printf("Case #%d: %.6lf\n" , ++kase , getProb(0 , L)) ;

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: