题目链接:http://poj.org/problem?id=1056
题意:给一些由0/1构成的编码,问问它们是不是存在某个编码为另一个编码的前缀。
思路:trie树解决字符串前缀问题。
我们把每个单词x加入trie树的时候考虑两种情况:
(1) 是否存在已加进去的单词y是x的前缀。
(2) 是否存在已加进去的单词y,x是y的前缀。
我们对每个单词的结尾字母节点进行标记。
对于(1),我们每次到达一个字母节点,去看看这个节点有没有被标记过。
对于(2),我们在当前单词的最后一个字母节点处,先看这个节点之前有没有被访问过,再对这个节点进行操作。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for(int i = j; i <= k; i++ )
#define Rrep(i,j,k) for(int i = j; i >= k; i-- )
#define Clean(x,y) memset(x,y,sizeof(x))
char temp[20];
struct trie
{
int next[1<<11][2];
bool end[1<<11];
int root;
int len;
void clear()
{
root = 0;
len = 0;
Clean(next,0);
Clean(end,false);
}
bool insert(char s[])
{
int now = root;
int k = strlen(s);
rep(i,0,k-1)
{
int index = s[i] - '0';
if ( i == k-1 && next[now][index] ) return false; // 判断(2)
if ( !next[now][index] ) next[now][index] = ++len;
now = next[now][index];
if ( end[now] ) return false; // 判断(1)
}
return end[now] = true;
}
}a;
int main()
{
int kase = 0;
while( gets(temp) )
{
bool can = true;
a.clear();
kase++;
while( temp[0] != '9' )
{
if ( can ) can = a.insert(temp);
gets(temp);
}
if ( can )
printf("Set %d is immediately decodable\n",kase);
else
printf("Set %d is not immediately decodable\n",kase);
}
return 0;
}