HDU 1305 Immediate Decodability
-
题意:一组01字符串,问是否存在一个字符串是另一个字符串的前缀。
-
两种方法
-
一:在沿途经过节点打标记,最后依次在终点询问 cnt[p]>=2
- 缺点:需要额外的空间储存输入的字符串,容易内存超限
- 二:(更优方法)在叶子节点打标记,沿途询问 cnt[p] 以及在终点询问 son[p][0] || son[p][1] 。不用额外储存。
- 思路:对01串建Trie,在建的过程中即可维护答案。
- 在插入结点时,若某结点是已有01串末尾结点,那该串一定有前缀。
- 或者在插入该串的末尾时,该结点是已有数字串的中间结点,那该串一定是某已有串的前缀。
方法一:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
int flag=1;
const int N=1e4+10;
int son[N][2],cnt[N],idx;
vector<string>vec;
void insert(string s)
{
int p=0,u;
for(int i=0;i<s.length();i++)
{
u=s[i]-'0';
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
cnt[p]++;
}
}
void init()
{
idx=0,flag=1; vec.clear();
for(int i=0;i<N;i++) son[i][0]=son[i][1]=cnt[i]=0;
}
bool que(string s)
{
int p=0,u;
for(int i=0;i<s.length();i++)
{
u=s[i]-'0';
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
}
if(cnt[p]>=2) return 0;
return 1;
}
int main()
{
string s;
int cas=1;
init();
while(cin>>s)
{
if(s=="9")
{
for(auto i:vec) flag*=que(i);
if(flag) cout<<"Set "<<cas<<" is immediately decodable\n";
else cout<<"Set "<<cas<<" is not immediately decodable\n";
cas++;
init();
continue;
}
insert(s); vec.push_back(s);
}
return 0;
}
方法二:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int flag=1;
const int N=1e4+10;
int son[N][2],cnt[N],idx;
int insert(string s)
{
int p=0,u;
for(int i=0;i<s.length();i++)
{
u=s[i]-'0';
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
if(cnt[p]) return 0;
}
cnt[p]++;
if(son[p][0] || son[p][1]) return 0;
return 1;
}
void init()
{
idx=0,flag=1;
for(int i=0;i<N;i++) son[i][0]=son[i][1]=cnt[i]=0;
}
int main()
{
string s;
int cas=1;
init();
while(cin>>s)
{
if(s=="9")
{
if(flag) cout<<"Set "<<cas<<" is immediately decodable\n";
else cout<<"Set "<<cas<<" is not immediately decodable\n";
cas++;
init();
continue;
}
if(flag) flag*=insert(s);
}
return 0;
}