Trie树实现

转自: http://www.cnblogs.com/ltang/archive/2010/11/25/1887573.html

解题思路:

  建立trie图,我们可以假设起点均为root节点,题目转化为求解root经过m步到达所有节点的总和

  dp求解,如果存在i->j的路径,counter[m, j]  += counter[m-1, i];初始条件为counter[0, root] = 1;

  显然,还需要使用高精度

 

  1 代码
  2 
  3 #include <iostream>
  4 #include <map>
  5 using namespace std;
  6 
  7 const int MAXP = 10;
  8 const int MAXL = 10;
  9 const int MAXN = 50;
 10 const int MAXNODS = MAXP * MAXL + 1;
 11 const int base = 1e9;
 12 
 13 int size, n, a, b;
 14 int trie[MAXNODS][MAXN];
 15 int queue[MAXNODS], suffix[MAXNODS];
 16 bool danger[MAXNODS], visited[MAXNODS];
 17 char letter[MAXP + 1];
 18 int counter[2][MAXNODS][21], ans[21];
 19 
 20 map<char, int>dic;
 21 
 22 void Build_Trie()
 23 {
 24     int t, len, p = 0;
 25     len = strlen(letter);
 26     for (int i = 0; i < len; i++)
 27     {
 28         t = dic[letter[i]];
 29         if (trie[p][t] == 0)  trie[p][t] = ++size;
 30         p = trie[p][t];
 31         if (danger[p]) break;
 32     }
 33     danger[p] = true;
 34 }
 35 
 36 void Build_Graph()
 37 {
 38     int head = 1, tail = 0;
 39     queue[0] = 0;
 40     for(int i = 0; i < n; i++)
 41         if (trie[0][i]) queue[++tail] = trie[0][i];    // 根节点所有子节点的后缀结点均为根节点
 42     while (head <= tail)
 43     {
 44         danger[queue[head]] |= danger[suffix[queue[head]]];    //后缀结点为危险节点,该节点也为危险节点
 45         if (!danger[queue[head]])
 46         {
 47             for(int i = 0; i < n; i++)
 48             {
 49                 if (trie[queue[head]][i] == 0)
 50                     trie[queue[head]][i] = trie[suffix[queue[head]]][i];//如果不存在i孩子,则指向后缀结点的i孩子
 51                 else
 52                 {
 53                     queue[++tail] = trie[queue[head]][i];
 54                     suffix[queue[tail]] = trie[suffix[queue[head]]][i];//计算后缀结点
 55                 }
 56             }
 57         }
 58         ++head;
 59     }
 60 }
 61 
 62 void add(int *p, int * q)
 63 {
 64     if (p[0] < q[0]) p[0] = q[0];
 65     for (int k = 1; k <= p[0]; k++)
 66     {
 67         p[k] += q[k];
 68         p[k + 1] += (p[k] / base);
 69         p[k] %= base;
 70     }
 71     if (p[p[0] + 1])p[0]++;
 72 }
 73 
 74 void bfs(int node)
 75 {
 76     if (visited[node])return;
 77     visited[node] = true;
 78     for (int i = 0; i < n; i++)
 79     {
 80         if (!danger[trie[node][i]])
 81         {
 82             add(counter[a][trie[node][i]], counter[b][node]);
 83             bfs(trie[node][i]);
 84         }
 85     }
 86 }
 87 
 88 void bfs_ans(int node)
 89 {
 90     if (visited[node]) return;
 91     visited[node] = true;
 92     add(ans, counter[a][node]);
 93     for (int i = 0; i < n; i++)
 94         if (!danger[trie[node][i]]) bfs_ans(trie[node][i]);
 95 }
 96 
 97 int main()
 98 {
 99     int p, m, ch, i;
100 
101     memset(danger, 0, sizeof(danger));
102     memset(trie, 0, sizeof(trie));
103 
104     scanf("%d %d %d\n", &n, &m, &p);
105     for (i = 0; i < n; i++)scanf("%c", &ch), dic[ch] = i;
106     for (i = 0; i < p; i++)scanf("%s", letter), Build_Trie();
107     Build_Graph();
108 
109     a = 1, b = 0;
110     counter[1][0][0] = counter[1][0][1] = 1;
111     for (i = 0; i < m; i++)
112     {
113         swap(a, b);
114         memset(visited, 0, sizeof(visited));
115         memset(counter[a], 0, sizeof(counter[a]));
116         bfs(0);
117     }
118     memset(visited, 0, sizeof(visited));
119     memset(ans, 0, sizeof(ans));
120     bfs_ans(0);
121     printf("%d", ans[ans[0]]);
122     for (i = ans[0] - 1; i > 0; i--)
123         printf("%.9d", ans[i]);
124     printf("\n");
125     return 0;
126 }

 

posted @ 2015-03-17 13:02  David_W  阅读(148)  评论(0编辑  收藏  举报