用struct写的静态字典树,感觉就是链式前向星的思想,原来是这么搞的,恍然大悟。
这个题就是需要加个结尾标记,进行两次判断,第一次判断前面是否存在这个字符串的前缀,第二次判断这个字符串是否为之前出现过的字符串的前缀。
剩下的就是手撕代码了。但是,TT,一定别那么大方了,如同吃了香蕉加大枣。别开100万,别开100万,别开100万,重要的事情说三遍,50万刚刚好。我还不信邪的开了70万试试,刚刚MLE,难受。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<string>
#include <set>
#include<time.h>
//a&3==a%4
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
const double eps=1e-8;
const int maxn=500010;//须填写
const int inf=0x3f3f3f3f;
struct node
{
int next[10];
bool isend;
int num;
node()
{
for(int i=0;i<10;i++)
{
next[i]=0;
}
isend=false;
num=0;
}
}tree[maxn];
int cnt;
bool inst(char str[])
{
int c;
int index=0;
int len=strlen(str);
for(int i=0;i<len;i++)
{
c=str[i]-'0';
if(tree[index].next[c]==0)
{
tree[index].next[c]=++cnt;
}
index=tree[index].next[c];
tree[index].num++;
if(tree[index].isend)
{
return false;
}
if(i==len-1)
{
tree[index].isend=true;
for(int i=0;i<10;i++)
{
if(tree[tree[index].next[i]].num>0)
return false;
}
}
}
return true;
}
int init()
{
cnt=0;
mem(tree);
return 1;
}
int main()
{
char str[10010];
int kase;
scanf("%d",&kase);
while(kase--)
{
init();
int n;
scanf("%d",&n);
bool flag=true;
for(int i=0;i<n;i++)
{
scanf("%s",str);
if(flag)
flag=inst(str);
}
if(flag)
{
printf("YES\n");
}
else{
printf("NO\n");
}
}
return 0;
}