题意:
给定n个串,找一个字符串u,设前缀为u的字符有v个,则权值为 u*v,求最大的权值
思路:把所有串插到字典树中,答案就是节点深度*该节点的覆盖数
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define ll int
struct node{
int pos, len;
node(ll a=0, ll b=0):pos(a),len(b){}
};
#define Word_Len 505000
#define Sigma_size 95
struct Trie{
ll ch[Word_Len][Sigma_size]; //Word_Len是字典树的节点数 若都是小写字母Sigma_size=26
ll Have_word[Word_Len]; //这个节点下有几个单词
ll val[Word_Len]; // 这个节点附带的信息,初始化为0表示这个节点不存在单词,所以节点带的信息必须!=0
ll sz ; //当前节点数
ll pre[Word_Len];
char he[Word_Len];
ll Newnode(){memset(ch[sz], 0, sizeof(ch[sz])); val[sz]=Have_word[sz]=0; return sz++;}
void init() //初始化字典树
{ sz = 0; Newnode();}//初始化
ll idx(char c){return c-32;} //字符串编号
void insert(char *s){ //把v数字加给 s单词最后一个字母
ll u = 0, len = strlen(s);
for(ll i = 0; i < len; i++){
int c = idx(s[i]);
if(!ch[u][c]) //节点不存在就新建后附加
{
he[sz] = s[i];
val[sz] = val[u]+1;
pre[sz] = u;
ch[u][c] = Newnode();
}
u = ch[u][c];
Have_word[u]++;
} //现在的u就是这个单词的最后一个位置
}
ll find_word(char *s){
ll u = 0, len = strlen(s);
for(ll i = 0; i < len; i++){
ll c = idx(s[i]);
if(!ch[u][c])return 0; //节点不存在
u = ch[u][c];
}
return Have_word[u];
}
void Have_name(char *s, ll now){
ll len = val[now];
s[len--] = '\0';
int cc = now;
while(cc!=-1)
{
s[len--] = he[cc];
cc = pre[cc];
}
}
ll find_ans(){
ll ans = 0;
queue<node>q; q.push(node(0,0));
while(!q.empty()){
node u = q.front(); q.pop();
ans = max(ans, Have_word[u.pos]*u.len);
for(ll i = 0; i < Sigma_size; i++){
node v = node(ch[u.pos][i], u.len+1);
if(v.pos)
q.push(v);
}
}
return ans;
}
};
Trie ac;
char s[1000];
int main(){
ll T, i, j, k, n;;scanf("%lld",&T);
while(T--){
ac.init();
scanf("%lld",&n);
while(n--){
scanf("%s",s);
ac.insert(s);
}
printf("%lld\n",ac.find_ans());
}
return 0;
}