这道题看着就是Trie题。但是难度在于动态分配节点会超时,需要静态提前分配好。
问题在于有多个test cases的情况下,如何不让前面的状态不要影响到后面的状态(不可能在每个test case之前把所有节点再初始化一次,肯定超时)。
我的解决方法是给每个节点加一个递增的version number,对应每次test case。事实证明这不是一个好方法。逻辑的复杂度增加不少。在“大致”正确(过了110, 1100和1100 110这种常见错误)后,仍然是WA。后来逻辑改成了每次用到新节点的时候,就把新节点初始化。这样逻辑清楚了很多。也就过了。
另外:本题最多有10000个number, 每个number最多10位,这意味着静态分配的trie节点至少要100000个,而不是number的最大个数。
thestoryofsnow | 3630 | Accepted | 4872K | 125MS | C++ | 1640B |
/*
ID: thestor1
LANG: C++
TASK: poj3630
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>
using namespace std;
const int MAXL = 10 + 1;
const int MAXN = 10000 * MAXL;
class Trie
{
public:
Trie *next[10];
bool isLeaf;
Trie()
{
init();
}
void init()
{
for (int i = 0; i < 10; ++i)
{
next[i] = NULL;
}
isLeaf = false;
}
};
Trie trie[MAXN];
bool insert(Trie *root, char number[], Trie trie[], int &trieNo)
{
bool isConsistent = false;
for (int i = 0; number[i] != '\0'; ++i)
{
int next = number[i] - '0';
// we have never been here in this test case
if (root->next[next] == NULL)
{
isConsistent = true;
root->next[next] = &trie[trieNo];
trie[trieNo].init();
// assert (root->next[next]->version < t);
trieNo++;
}
root = root->next[next];
// some words end here, so they are prefixes of this number
if (root->isLeaf)
{
return false;
}
}
root->isLeaf = true;
return isConsistent;
}
int main()
{
int T;
scanf("%d", &T);
char number[MAXL];
Trie *root = &trie[0];
for (int t = 0; t < T; ++t)
{
root->init();
int N;
scanf("%d", &N);
bool isConsistent = true;
int trieNo = 1;
for (int i = 0; i < N; ++i)
{
scanf("%s", number);
if (isConsistent && !insert(root, number, trie, trieNo))
{
isConsistent = false;
}
}
if (isConsistent)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}