这道题可以通过排序后,对于每个串只需与其前一个串与后一个串做比较来查前缀得出答案。
我采用的是字典树(Trie), 昨天学的是动态建立的树,导致TLE。 然后学习了一下静态建立字典树。
思路:插入串时检查当前插入串是不是之前已插入串的前缀,以及检查已插入串是不是当前插入串的前缀。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int NUM = 10;
const int N = 100005;
typedef struct Trie
{
Trie* next[NUM];
int cnt;
void init()
{
memset(next, NULL, sizeof(next));
cnt = 0;
}
};
Trie pool[N], *root;
int sz;
int flag;
void getNode(Trie* p)
{
p->init();
}
void init()
{
root = &pool[0];
getNode(root);
root->init();
sz = 1;
}
void myInsert(char* str)
{
Trie* p = root;
int i = 0;
int tflag = 1; //用于标记 当前插入串 是某个已插入串的前缀 如 9115678 911
while(str[i])
{
int ch = str[i] - '0';
if(p->next[ch] == NULL)
{
p->next[ch] = &pool[sz++];
getNode(p->next[ch]);
tflag = 0;
}
if(p->cnt)
{
flag = 0; //短串作为当前插入串的前缀,如 911 9115678 则已得答案
return;
}//
p = p->next[ch];
i++;
}
if(tflag) {
flag = 0; //如果当前插入串 是某个已插入串的前缀,则已得答案
}
p->cnt++;
}
int main()
{
int t;
scanf("%d", &t);
char number[16];
while(t--)
{
init();
if(root == NULL) printf("!");
int n;
scanf("%d", &n);
flag = 1;
for(int i = 0; i < n; i++)
{
scanf("%s", number);
if(flag)
myInsert(number);
}//
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}