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: 絢麗的手鏈