题意:求给定的多个串中是否存在,某个串是另一个串的前缀。
解题思路:使用Trie树。在每次插入一个串的同时判断。对于该问题,只存在以下两种情况:
1.当前插入的串的前缀是前面的某个串。对于这种情况,把前面插入的串的最后一个节点记为危险节点。那么在后面插入串的时候,如果经过危险节点,说明这种情况成立。
2.当前插入的串是前面某个串的前缀。对于这种情况,把插入串的最后一个节点单独拿出来判断,如果该串的最后一个节点已经被分配过地址,则说明这种情况成立。
这两个条件只要满足一个,即回答NO。
代码如下:
//#include <bits/stdc++.h>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxnode = 1e6 + 10;
const int sigma_size = 10;
const int maxn = 1e4 + 10;
int flag;
struct Trie {
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
Trie() {sz = 1;memset(ch[0] , 0, sizeof(ch[0]));}
int idx(char c) {return c - '0';}
void insert(char * s, int v){
int u = 0,n = strlen(s);
for(int i = 0;i < n;i++){
int c = idx(s[i]);
if(i == n - 1 && ch[u][c]) flag = 0;
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
if(val[ch[u][c]]!=0) flag = 0;
u = ch[u][c];
}
val[u] = v;
}
void clear(){
sz = 1;memset(ch[0] , 0, sizeof(ch[0]));
}
}T;
char s[maxn];
int n;
int main()
{
int kase;scanf("%d",&kase);
while(kase--){
T.clear();flag = 1;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%s",s);
T.insert(s,i);
}
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}