典型的字典树题目,只是有所变型。题意:在一组字符串中,它的goodness前缀数是最长公共前缀长度乘以拥有共同前缀的字符串数量的值中的最大值。比如第一个样例,前两个字符串有最长的公共前缀000,长度为3,那么这一组字符串的goodness前缀数为3*2=6。而第二个样例,两个字符串的公共前缀为0,长度为1,1*2=2,但是两个字符串都是长度为20,每个字符串本身算一个公共前缀,那么goodness前缀数为20*1=20。现在,请求出每个测试样例给出的一组字符串中的goodness前缀数。
我的解题思路:字典树存储字符串时记录一下当前位置的字符是第几次存储以及当前字符在第几个字符的位置,然后将两者相乘与要输出的答案变量比较之后去最大值,每次存储一个字符的时候都比较一下就行了。理解了就是比较简单了,字符只有0或者1两种,但是字符串的长度却可以达到200。所以总的来说,数据也不算小。
我的解题代码:静态字典树解题
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 50001
#define M 202
struct DT //字典树结构体
{
int chid[2];
int num; //当前位置的字符出现的次数
void init()
{
num = 0;
memset(chid, -1, sizeof(chid));
}
};
DT dt[N*10];
int nn;
char str[N][M];
int t, n;
int ans;
void Init(); //初始化
void Read(); //输入
void Insert(char s[]); //插入字符串到字典树中,并寻找最佳答案
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
Init();
Read();
printf("%d\n", ans);
}
return 0;
}
void Init()
{
nn = ans = 0;
for (int i=0; i<N*10; ++i)
{
dt[i].init();
}
return;
}
void Read()
{
for (int i=0; i<n; ++i)
{
scanf("%s", str[i]);
Insert(str[i]);
}
return;
}
void Insert(char s[])
{
int x = 0;
int chnum;
int sn = strlen(s);
for (int i=0; i<sn; ++i)
{
chnum = s[i] - '0';
if (dt[x].chid[chnum] == -1)
{
dt[x].chid[chnum] = ++nn;
}
x = dt[x].chid[chnum];
dt[x].num++;
ans = max(ans, (i + 1) * dt[x].num); //比较最大的goodness前缀数
}
return;
}