問題描述
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;
}