csu 1987: 绚丽的手链

Posted 极速快码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csu 1987: 绚丽的手链相关的知识,希望对你有一定的参考价值。

1987: 绚丽的手链

        Time Limit: 6 Sec     Memory Limit: 512 Mb     Submitted: 13     Solved: 2    


Description

小X的妹妹马上就要过生日了,作为哥哥,小X打算买一些手链送给妹妹。

采购完礼物回到家的小X惊奇的发现:每条手链虽然只由两种颜色的珠子串成,但是它们有一个神奇的效果,那就是当多条手链同时放在一起时,会散发出绚丽夺目的光芒。光芒的绚丽程度有强有弱,这取决于手链的最长公共前缀的长度和手链数目的乘积。例如000,001,0011三串手链放在一起会发出绚丽程度为6的光芒。

显然如果将所有手链都送给妹妹,效果未必最好,因此他决定从中挑选一些送给妹妹,使得能够达到最绚丽的效果。你能帮助他吗?

Input

第一行一个整数 T (≤ 20) 表示数据组数。

每组数据第一行一个整数 n(≤ 50000) 代表字符串的数量。接下来N行,每行为一个仅由0,1组成的字符串代表小X购买的手链,手链的最大长度为200。

Output

对于每组数据输出一行, 表示小X经过挑选后送给妹妹的手链所能产生的最大绚丽程度。

Sample Input

4
4
0000
0001
10101
010
2
01010010101010101010
11010010101010101010
3
010101010101000010001010
010101010101000010001000
010101010101000010001010
5
01010101010100001010010010100101
01010101010100001010011010101010
00001010101010110101
0001010101011010101
00010101010101001 

Sample Output

6
20
66
44 

Hint

Source

2017年暑期集训校队选拔

Author

徐戍

 

 

题解:

这个题目是真的不好做    心累

6次超时   还有几次其他的错误    

我的第一想法就是   构建字典树  节点记录下着是几个字符串的公共子串   (这个不难)  然后就是一次遍历字典树   求出答案   结果超时

然后  我发现建树之后其实不用去遍历了    我们在建树的时候   就可以得到答案    结果还是超时

下面的超时的那个代码    各位大佬谁会优化的   告诉一下我怎么优化   0.0    (后面有AC代码)

 1 #include <cstdio>
 2 #include <time.h>
 3 #include <cmath>
 4 #include <map>
 5 #include <stdlib.h>
 6 #include <cstring>
 7 using namespace std;
 8 char s[205];
 9 int ans;
10 struct Trie
11 {
12     int num;
13     struct Trie *nxt[2];
14     Trie()
15     {
16         num=0;
17         for(int i=0; i<2; i++)
18         {
19             nxt[i]=NULL;
20         }
21     }
22 };
23 
24 void Trie_Inser(Trie *p,char s[])
25 {
26     int i=0;
27     Trie *q=p;
28     while(s[i])
29     {
30         int nx=s[i]-0;
31         if(q->nxt[nx]==NULL)
32         {
33             q->nxt[nx]=new Trie;
34         }
35         i++;
36         q=q->nxt[nx];
37         q->num++;
38         ans=max(ans,(q->num)*i);
39     }
40 }
41 int main()
42 {
43     int n,m;
44     scanf("%d",&n);
45     while(n--)
46     {
47         ans=0;
48         Trie *p=new Trie;
49         scanf("%d",&m);
50         getchar();
51         while(m--)
52         {
53             gets(s);
54             Trie_Inser(p,s);
55         }
56 
57                 printf("%d\n",ans);
58 
59     }
60     return 0;
61 }

 

 

在我觉得动态字典树的做法没有救了之后    我尝试了一下动态字典树的    说的简单点就是使用数组去模拟   

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 
 5 using namespace std;
 6 int pos,ans;
 7 struct node
 8 {
 9     int num;
10     int child[2];
11 }tree[10000010];
12 
13 int add()
14 {
15     pos++;
16     tree[pos].num=0;
17     for(int i=0;i<2;i++)
18     {
19         tree[pos].child[i]=-1;
20     }
21     return pos;
22 }
23 
24 int inser(char* str)
25 {
26     int post=0;
27     int tmp=0;
28     int len=strlen(str);
29     for(int i=0;i<len;i++)
30     {
31         int m=str[i]-0;
32         if(tree[post].child[m]==-1)
33         {
34             if(tmp==0)
35                 tmp=i+1;
36             tree[post].child[m]=add();
37         }
38 
39         post=tree[post].child[m];
40         tree[post].num++;
41           ans=max(ans,tree[post].num*(i+1));
42     }
43     if(!tmp)
44         tmp=len;
45     return tmp;
46 }
47 
48 char arr[1000010];
49 int main()
50 {
51     int T;
52     scanf("%d",&T);
53     for(int t=1;t<=T;t++)
54     {
55         int n;
56         pos=0;
57         memset(tree[0].child,-1,sizeof(tree[0].child));
58         scanf("%d",&n);
59         ans=0;
60         for(int i=0;i<n;i++)
61         {
62             scanf("%s",&arr);
63             int k=inser(arr);
64         }
65         cout<<ans<<endl;
66     }
67     return 0;
68 }

 

以上是关于csu 1987: 绚丽的手链的主要内容,如果未能解决你的问题,请参考以下文章

P1-2017级第一次算法上机 E 比特手链

LQ0105 手链样式字符串

紫色的手链(求最大值和次大值的异或值最大)

bzoj1625 / P2871 [USACO07DEC]手链Charm Bracelet

模拟Vijos P1926 紫色的手链

[USACO07DEC]手链Charm Bracelet——01背包