题目大意:给你 n 个字符串,然后让你找出其中的一个集合 S,设 P(S)为S集合中所有字符串的公共前缀长度*字符串个数,让你求出
P的最大值。
思路:因为是前缀的问题,可以想到用 trie 。把字符串全都插进去,然后扫描每个节点,那么就是所有的P,该节点的P = 它到根节点的
距离*经过这个节点的字符串个数,找出最大值即可。思路是有了,可是这道题还有一个地方,那就是空间问题,算一下是 10^8 ,但 UVA
好像不考虑空间来着,这么大的数组,我竟然过了。。 = = ,其实应该是MLE的,那怎么办呢,写 trie 的指针形式呗!
P的最大值。
思路:因为是前缀的问题,可以想到用 trie 。把字符串全都插进去,然后扫描每个节点,那么就是所有的P,该节点的P = 它到根节点的
距离*经过这个节点的字符串个数,找出最大值即可。思路是有了,可是这道题还有一个地方,那就是空间问题,算一下是 10^8 ,但 UVA
好像不考虑空间来着,这么大的数组,我竟然过了。。 = = ,其实应该是MLE的,那怎么办呢,写 trie 的指针形式呗!
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX_NODE = 50000*201;
const int SIGMA_SIZE = 2;
int ans;
struct Node
{
Node* ch[SIGMA_SIZE];
int val;
Node()
{
ch[0] = NULL;
ch[1] = NULL;
val = 0;
}
};
struct Trie
{
Node *root;
void init()
{
root = new Node();
}
int idx(char c)
{
return c - '0';
}
void insert(char *s)
{
Node* u = root;
int len = strlen(s);
for(int i = 0;i < len;i++)
{
int c = idx(s[i]);
if(u->ch[c] == NULL)
{
u->ch[c] = new Node();
}
u = u->ch[c];
u->val++;
}
}
void solve(Node* u,int len)
{
ans = max(ans,len*(u->val));
for(int i = 0;i < SIGMA_SIZE;i++)
{
if(u->ch[i])
solve(u->ch[i],len+1);
}
delete u;
}
}trie;
char str[222];
int main()
{
int _;
scanf("%d",&_);
while(_--)
{
trie.init();
int n;
scanf("%d",&n);
for(int i = 0;i < n;i++)
{
scanf("%s",str);
trie.insert(str);
}
ans = 0;
trie.solve(trie.root,0);
printf("%d\n",ans);
}
return 0;
}