这题跟杭电1671一样,->详情请戳这里<-
于是用1671的代码去提交了一发,结果TLE了。果断写成静态树,效率笋尖就上去了,从TLE到125ms,就是这么快!
这个代码拿到杭电上重新提交一遍,效率也高出不少。从400+ms到93ms,果然静态数据结构效率高。这题与1671比还改进了一点,就是去掉了排序,在每个节点处加了一个变量tag,表示某条路径存在,end标记一个单词的结尾,这样我们就不用排序,就可以判断2个单词是否有相同前缀了。无非分2种情况:
1:某个单词到了结尾,发现该节点的tag为1,表示前面插入的某个单词已经走过这条路了,即本单词是该单词的前缀,否定之;
2:某个单词在插入的路径上发现某节点是另一个单词的结尾,则这2个单词有共同前缀,否定之。
废话不多说,上代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node
{
int next[10];
int end,tag;
}lcm[1<<16];
int pos,n;
int flag;
char s[11];
void init(int i)
{
memset(lcm[i].next,0,sizeof(lcm[i].next));
lcm[i].end = lcm[i].tag = 0;
}
void build(int t,int id)
{
lcm[t].tag = 1;
if(lcm[t].end == 1)
flag = 1;
if(flag)
return;
if(lcm[t].next[s[id] - '0'] == 0)
{
lcm[t].next[s[id] - '0'] = pos;
init(pos);
pos ++;
}
if(s[id + 1] == '\0')
{
if(lcm[lcm[t].next[s[id] - '0']].tag == 1)
flag = 1;
lcm[lcm[t].next[s[id] - '0']].end = 1;
return;
}
else
build(lcm[t].next[s[id] - '0'],id + 1);
}
int main()
{
int i,t;
scanf("%d",&t);
while(t --)
{
scanf("%d",&n);
pos = 1;
init(0);
flag = 0;
//memset(lcm,0,sizeof(lcm));
for(i = 0;i < n;i ++)
{
scanf("%s",s);
s[strlen(s)] = '\0';
build(0,0);
}
if(flag)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
//2780K 125MS
/*
10
2
123
12
2
1
12
2
12
1
3
1
12
123
3
12
13
14
3
12
13
123
3
911
97625999
91125426
5
113
12340
123440
12345
98346
*/