POJ 1056 IMMEDIATEDECODABILITY(字典树Trie)
http://poj.org/problem?id=1056
题意:
给你一个由很多01字符串组成的集合,问你集合中有没有一个字符串是其他另外一个或多个字符串的前缀.
分析:
直接建立字典树,并且在插入字符串的时候判断有没有该字符串的前缀或有没有包含该字符串的长字符串即可.
假设该集合存在单词A和单词B且A是B的前缀,那么如果A先输入,B后输入。则再用B插入字典树的过程中,会遇到一个val>0的节点,此时我们可知道存在前缀。如果B先输入,A后输入,则在插入A的时候,我们会发现A在字典树中的终节点还有儿子存在(即通往B的道路),此时我们知道存在以A为前缀的单词。
AC代码:
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxnode = 80;
const int sigma_size=2;
struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;
}
bool insert(char *s)
{
int n=strlen(s),u=0;
bool ok=true;
for(int i=0;i<n;i++)
{
int id=s[i]-'0';
if(ch[u][id]==0)
{
ch[u][id]=sz;
val[sz]=0;
memset(ch[sz],0,sizeof(ch[sz]));
sz++;
}
u=ch[u][id];
if(val[u])//存在前缀
{
ok=false;
break;
}
}
val[u]=1;
for(int i=0;i<sigma_size;i++)
if(ch[u][i]!=0)//存在超集
{
ok=false;
break;
}
return ok;
}
};
Trie trie;
char word[10];
int main()
{
trie.init();
bool ok=true;
int kase=0;
while(gets(word))
{
if(strcmp(word,"9")==0)
{
if(ok) printf("Set %d is immediately decodable\n",++kase);
else printf("Set %d is not immediately decodable\n",++kase);
trie.init();
ok=true;
continue;
}
if(ok)
ok=trie.insert(word);
}
return 0;
}