题意:给你n个串,对于一个前缀,如果出现k次,就会得到前缀的长度*k,现在让你求长度*k的最大值。
题解:用trie树来搞。把每个串插入到trie中,记录每个子串出现的次数以及长度,trie树很容易实现,然后插完之后,把每个节点遍历一遍,求最大的len*sum,输出即可。
1 #include<cstring> 2 #include<vector> 3 #include<cstdio> 4 using namespace std; 5 const int maxnode = 4000 * 1000 + 10; 6 const int sigma_size = 26; 7 char word[10002]; 8 int n,m; 9 int sz; 10 struct Trie { 11 int head[maxnode]; // head[i]为第i个结点的左儿子编号 12 int next[maxnode]; // next[i]为第i个结点的右兄弟编号 13 char ch[maxnode]; // ch[i]为第i个结点上的字符 14 int sum[maxnode]; 15 int len[maxnode]; 16 void clear() { 17 sz = 1; 18 head[0] = next[0] = 0; 19 memset(len,0,sizeof(len)); 20 memset(sum,0,sizeof(sum)); 21 } 22 void insert(const char *s,int form ,int to) { 23 int u = 0, v; 24 for(int i = form; i <to; i++) { 25 bool found = false; 26 for(v = head[u]; v != 0; v = next[v]) 27 if(ch[v] == s[i]) { // 找到了 28 found = true; 29 break; 30 } 31 if(!found) { 32 v = sz++; // 新建结点 33 ch[v] = s[i]; 34 next[v] = head[u]; 35 head[u] = v; // 插入到链表的首部 36 head[v] = 0; 37 } 38 u = v; 39 sum[u]++; 40 len[u]=i+1; 41 } 42 } 43 }trie; 44 int cas; 45 int main() { 46 scanf("%d",&cas); 47 while(cas--) { 48 trie.clear(); 49 scanf("%d",&n); 50 for(int i=1;i<=n;i++){ 51 scanf("%s", word); 52 m=strlen(word); 53 trie.insert(word,0,m); 54 } 55 int ans=0; 56 for(int i=1;i<sz;i++){ 57 ans=max(ans,trie.len[i]*trie.sum[i]); 58 } 59 printf("%d ",ans); 60 } 61 return 0; 62 }