题目链接:
http://poj.org/problem?id=3630
题意:
给你一串长度小于等于10的电话号码,问你,其中的一个是不是其他的前缀,如果是的话,就输出NO,全部不满足就YES。
题解:
典型的字典树的题目,但是直接动态建树,会超时,这里我们需要采用静态建树。
什么是动态建树,什么是静态建树,这里安利一个大佬的链接:
http://www.cnblogs.com/George1994/p/6346790.html
代码1(字典树静态建树)
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f;
const int maxn = 1e5+10;
struct Tire
{
int cnt;
struct Tire *next[10];
Tire()
{
cnt=0;
for(int i=0;i<10;i++)
next[i]=NULL;
}
}tree[maxn];
string s[maxn];
int total;
void insert(Tire *&root,string s)
{
int len=s.size();
Tire *p=root;
for(int i=0;i<len;i++)
{
int pos=s[i]-'0';
if(!p->next[pos])
{
p->next[pos]=&tree[total];
total++;
}
p=p->next[pos];
p->cnt++;
}
return;
}
int search(Tire *&root,string s)
{
int len=s.size();
Tire *p=root;
if(root==NULL)
return 0;
for(int i=0;i<len;i++)
{
int pos=s[i]-'0';
p=p->next[pos];
if(p->cnt==1)
return 1;
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
met(tree,0);
Tire *root=&tree[0];
total=1;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>>s[i];
insert(root,s[i]);
}
int flag=0;
for(int i=0;i<n;i++)
{
if(!search(root,s[i]))
{
flag=1;
break;
}
}
if(flag)
printf("NO\n");
else
printf("YES\n");
}
}
代码2(STL):
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f;
const int maxn = 1e4+10;
vector<string> p;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
p.clear();
for(int i=0;i<n;i++)
{
string s;
cin>>s;
p.push_back(s);
}
sort(p.begin(),p.end());
bool flag=true;
for(int i=0;i<p.size()-1;i++)
{
if(p[i+1].find(p[i])==0)
{
flag=false;
break;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
}