问题描述
ZJM 收到了 Q老师 送来的生日礼物,但是被 Q老师 加密了。只有 ZJM 能够回答对 Q老师 的问题,Q老师 才会把密码告诉 ZJM。
Q老师 给了 ZJM 一些仅有 01 组成的二进制编码串, 他问 ZJM:是否存在一个串是另一个串的前缀.
Input
多组数据。每组数据中包含多个仅有01组成的字符串,以一个9作为该组数据结束的标志。
Output
对于第 k 组数据(从1开始标号),如果不存在一个字符串使另一个的前缀,输出"Set k is immediately decodable",否则输出"Set k is not immediately decodable"。
每组数据的输出单独一行
Sample input
01
10
0010
0000
9
01
10
010
0000
9
Sample output
Set 1 is immediately decodable
Set 2 is not immediately decodable
解题思路
这是一道基本的字典树题目,我们判断是否有前缀可以在插入的时候直接判断,假设当前字符串是S,有两种情况。
- 之前插入串是否是S的前缀
- S是否是之前插入串的前缀
对于第一种情况,我们只需要在插入S的过程中,判断路径上是否有结束的位置,如果有,则之前插入的串有S的前缀,否则没有。
对于第二种情况,在S插入到最后一个位置的时候,判断最后一个字母是否已经存在,如果存在,那么S就是其他串的前缀,否则没有。
完整代码
//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
struct Trie{
static const int NodeNum=1010,charset=2;
int tot,root,child[NodeNum][charset],flag[NodeNum];
Trie(){
memset(child,-1,sizeof(child));
root=tot=0;
}
void clear(){
memset(child,-1,sizeof(child));
root=tot=0;
}
bool insert(char *str){
int now=root,len=strlen(str);
for (int i=0; i<len; i++){
int x=str[i]-'0';
if(child[now][x]==-1){
child[now][x]=++tot;
flag[now]=0;
}
else if(i==len-1 || flag[child[now][x]]) return true;
now=child[now][x];
}
flag[now]=1;
return false;
}
};
const int maxn=100000+10;
char str[maxn];
int getint(){
int x=0,s=1; char ch=' ';
while(ch<'0' || ch>'9'){ ch=getchar(); if(ch=='-') s=-1;}
while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar();}
return x*s;
}
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
int cnt=0;
bool f=false;
Trie trieTree;
while(scanf("%s",str)!=EOF){
if(str[0]=='9'){
cnt++;
printf("Set %d is ",cnt);
if(f) printf("not ");
printf("immediately decodable\n");
f=false; trieTree.clear();
}
else f=trieTree.insert(str);
}
return 0;
}