POJ 1625 Censored!

解题思路:

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

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

  显然,还需要使用高精度

 

代码如下:

代码
#include <iostream>
#include
<map>
using namespace std;

const int MAXP = 10;
const int MAXL = 10;
const int MAXN = 50;
const int MAXNODS = MAXP * MAXL + 1;
const int base = 1e9;

int size, n, a, b;
int trie[MAXNODS][MAXN];
int queue[MAXNODS], suffix[MAXNODS];
bool danger[MAXNODS], visited[MAXNODS];
char letter[MAXP + 1];
int counter[2][MAXNODS][21], ans[21];

map
<char, int>dic;

void Build_Trie()
{
int t, len, p = 0;
len
= strlen(letter);
for (int i = 0; i < len; i++)
{
t
= dic[letter[i]];
if (trie[p][t] == 0) trie[p][t] = ++size;
p
= trie[p][t];
if (danger[p]) break;
}
danger[p]
= true;
}

void Build_Graph()
{
int head = 1, tail = 0;
queue[
0] = 0;
for(int i = 0; i < n; i++)
if (trie[0][i]) queue[++tail] = trie[0][i]; // 根节点所有子节点的后缀结点均为根节点
while (head <= tail)
{
danger[queue[head]]
|= danger[suffix[queue[head]]]; //后缀结点为危险节点,该节点也为危险节点
if (!danger[queue[head]])
{
for(int i = 0; i < n; i++)
{
if (trie[queue[head]][i] == 0)
trie[queue[head]][i]
= trie[suffix[queue[head]]][i];//如果不存在i孩子,则指向后缀结点的i孩子
else
{
queue[
++tail] = trie[queue[head]][i];
suffix[queue[tail]]
= trie[suffix[queue[head]]][i];//计算后缀结点
}
}
}
++head;
}
}

void add(int *p, int * q)
{
if (p[0] < q[0]) p[0] = q[0];
for (int k = 1; k <= p[0]; k++)
{
p[k]
+= q[k];
p[k
+ 1] += (p[k] / base);
p[k]
%= base;
}
if (p[p[0] + 1])p[0]++;
}

void bfs(int node)
{
if (visited[node])return;
visited[node]
= true;
for (int i = 0; i < n; i++)
{
if (!danger[trie[node][i]])
{
add(counter[a][trie[node][i]], counter[b][node]);
bfs(trie[node][i]);
}
}
}

void bfs_ans(int node)
{
if (visited[node]) return;
visited[node]
= true;
add(ans, counter[a][node]);
for (int i = 0; i < n; i++)
if (!danger[trie[node][i]]) bfs_ans(trie[node][i]);
}

int main()
{
int p, m, ch, i;

memset(danger,
0, sizeof(danger));
memset(trie,
0, sizeof(trie));

scanf(
"%d %d %d\n", &n, &m, &p);
for (i = 0; i < n; i++)scanf("%c", &ch), dic[ch] = i;
for (i = 0; i < p; i++)scanf("%s", letter), Build_Trie();
Build_Graph();

a
= 1, b = 0;
counter[
1][0][0] = counter[1][0][1] = 1;
for (i = 0; i < m; i++)
{
swap(a, b);
memset(visited,
0, sizeof(visited));
memset(counter[a],
0, sizeof(counter[a]));
bfs(
0);
}
memset(visited,
0, sizeof(visited));
memset(ans,
0, sizeof(ans));
bfs_ans(
0);
printf(
"%d", ans[ans[0]]);
for (i = ans[0] - 1; i > 0; i--)
printf(
"%.9d", ans[i]);
printf(
"\n");
return 0;
}

 

 

posted on 2010-11-25 13:45  ltang  阅读(1020)  评论(3编辑  收藏  举报

导航