uva 11468 Substring

题意:给你 k 个模板串,然后给你一些字符的出现概率,然后给你一个长度 l ,问你这些字符组成的长度为 l 的字符串不包含任何一个模板串的概率。

思路:AC自动机+概论DP

首先用K个模板构造好AC自动机。题目上说长L的新串的子串不包含任何一个K串,其实就是说在构造好的树中,从根往下走L步都不包含K个模板。此题用match标记是否为K模板串。

状态转移方程代码中注释了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<cstdio>
  5 #include<map>
  6 #include<string>
  7 using namespace std;
  8 
  9 const int SIGMA_SIZE = 64;
 10 const int MAXNODE = 500; // 结点总数
 11 const int MAXS = 20 + 10; // 模板个数
 12 
 13 int idx[256], n;
 14 double prob[SIGMA_SIZE];
 15 
 16 struct AhoCorasickAutomata
 17 {
 18     int ch[MAXNODE][SIGMA_SIZE];
 19     int f[MAXNODE];    // fail函数
 20     int match[MAXNODE];  // 是否包含某一个字符串
 21     int sz;            // 结点总数
 22 
 23     void init()
 24     {
 25         sz = 1;
 26         memset(ch[0], 0, sizeof(ch[0]));
 27     }
 28 
 29     // 插入字符串
 30     void insert(char *s)
 31     {
 32         int u = 0, n = strlen(s);
 33         for(int i = 0; i < n; i++)
 34         {
 35             int c = idx[s[i]];
 36             if(!ch[u][c])
 37             {
 38                 memset(ch[sz], 0, sizeof(ch[sz]));
 39                 match[sz] = 0;
 40                 ch[u][c] = sz++;
 41             }
 42             u = ch[u][c];
 43         }
 44         match[u] = 1;
 45     }
 46 
 47     // 计算fail函数
 48     void getFail()
 49     {
 50         queue<int> q;
 51         f[0] = 0;
 52         // 初始化队列
 53         for(int c = 0; c < SIGMA_SIZE; c++)
 54         {
 55             int u = ch[0][c];
 56             if(u)
 57             {
 58                 f[u] = 0;
 59                 q.push(u);
 60             }
 61         }
 62         // 按BFS顺序计算fail
 63         while(!q.empty())
 64         {
 65             int r = q.front();
 66             q.pop();
 67             for(int c = 0; c < SIGMA_SIZE; c++)
 68             {
 69                 int u = ch[r][c];
 70                 if(!u)
 71                 {
 72                     ch[r][c] = ch[f[r]][c];
 73                     continue;
 74                 }
 75                 q.push(u);
 76                 int v = f[r];
 77                 while(v && !ch[v][c]) v = f[v];
 78                 f[u] = ch[v][c];
 79                 match[u] |= match[f[u]];
 80             }
 81         }
 82     }
 83 };
 84 
 85 AhoCorasickAutomata ac;
 86 
 87 double d[MAXNODE][105];
 88 int vis[MAXNODE][105];
 89 
 90 double getProb(int u, int L)//d[u][L]=prob[u]*d[v][L-1]状态转方程 v为u的儿子可以走节点
 91 {
 92     if(!L) return 1.0;
 93     if(vis[u][L])
 94         return d[u][L];
 95     vis[u][L] = 1;
 96     d[u][L]=0.0;
 97     for(int i = 0; i < n; i++)
 98         if(!ac.match[ac.ch[u][i]])
 99             d[u][L] += prob[i] * getProb(ac.ch[u][i], L-1);
100     return d[u][L];
101 }
102 
103 char s[30][30];
104 
105 int main()
106 {
107     int T;
108     scanf("%d", &T);
109     for(int kase = 1; kase <= T; kase++)
110     {
111         int k, L;
112         scanf("%d", &k);
113         for(int i = 0; i < k; i++) scanf("%s", s[i]);
114         scanf("%d", &n);
115         for(int i = 0; i < n; i++)
116         {
117             char ch[9];
118             scanf("%s%lf", ch, &prob[i]);
119             idx[ch[0]] = i;
120         }
121         ac.init();
122         for(int i = 0; i < k; i++) ac.insert(s[i]);
123         ac.getFail();
124         scanf("%d", &L);
125         memset(vis, 0, sizeof(vis));
126         memset(d,0,sizeof(d));
127         printf("Case #%d: %.6lf\n", kase, getProb(0, L));
128     }
129     return 0;
130 }
View Code

 

posted @ 2015-12-06 21:24  yyblues  阅读(362)  评论(0编辑  收藏  举报