题意:判断是否有序列是另一序列的前缀。
算法:
1、可以先把序列按长度排序,然后用TRIE找前面序列是否是后面序列的前缀。
2、如果不排序,则既要判断前面是否是后面的前缀,又要判断后面是否是前面的前缀。
分别是 由于序列末尾的v=1,则第一种情况一定会中途遍历到v=1的节点。
后一种情况一定是 当前序列已经到了末尾,而它的next[i]至少有一个不为空。
另外若两个序列相等,就是即将要标记为v=1的节点已经是1。
malloc申请空间的trie超时了。。。。
只能改为静态数组。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
struct node
{
int v;
node* next[10];
}trie[1000000];
int c,flag;
void init(node* &rt)
{
rt = &trie[c++];
memset(trie,0,sizeof(trie));
rt->v = 0;
}
void insert(char s[],node *rt)
{
int len = strlen(s);
node *t;
for(int i=0;i<len;i++)
{
int id = s[i]-'0';
if(rt->next[id]==NULL)
{
t = &trie[c++];
t->v = 0;
rt->next[id] = t;
}
if(rt->next[id]->v==1) //如果之前有一个短序列是它的前缀
{
flag = 1;
return;
}
rt = rt->next[id];
}
for(int i=0;i<10;i++) //如果当前序列为之前一个长序列的前缀
{
if(rt->next[i]!=NULL)
{
flag = 1;
return;
}
}
if(rt->v==1) //如果当前序列和之前的序列相等
flag = 1;
else rt->v = 1;
}
int main()
{
int T,n;
char s[15];
node *rt;
scanf("%d",&T);
while(T--)
{
c = 0,flag = 0;
init(rt);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
if(!flag)
insert(s,rt);
}
if(flag)
puts("NO");
else puts("YES");
}
return 0;
}