Submit: 735 Solved: 102
[Submit][Status][Discuss]
Description
給你一個字符集合,你從其中找出一些字串出來. 希望你找出來的這些字串的最長公共字首*字串的總個數最大化.
Input
第一行給出數字N.N在[2,1000000] 下面N行描述這些字串,長度不超過20000 。保證輸入檔案不超過10MB
Output
a single line with an integer representing the maximal level of complexity Lc(T).
Sample Input
7
Jora de Sus
Orhei
Jora de Mijloc
Joreni
Jora de Jos
Japca
Orheiul Vechi
Jora de Sus
Orhei
Jora de Mijloc
Joreni
Jora de Jos
Japca
Orheiul Vechi
Sample Output
24
HINT
這題有毒啊,,
思路和演算法沒什麼好說的,
就是建一棵字典樹,統計好深度和個數,然後乘起來,取最大值
但是!!!
本蒟蒻一開始寫的無限RE
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int n,sz=1,ans; 6 string ch; 7 int a[500001][53],f[500001]; 8 void insert() 9 { 10 int l=ch.length(),now=0; 11 for(int i=0;i<l;i++) 12 { 13 int t; 14 if(ch[i]==' ')t=52; 15 else if(ch[i]<='Z')t=ch[i]-'A'; 16 else t=ch[i]-'a'+26; 17 if(a[now][t])now=a[now][t]; 18 else now=a[now][t]=++sz; 19 f[now]++; 20 ans=max(ans,f[now]*(i+1)); 21 } 22 } 23 int main() 24 { 25 scanf("%d",&n); 26 for(int i=1;i<=n;i++) 27 { 28 getline(cin,ch); 29 insert(); 30 } 31 printf("%d",ans); 32 return 0; 33 }
後來聽別人說這題卡記憶體,
於是我換成了前向星儲存,
然後,
無限TLE,
加了各種常數優化還是無限TLE
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 using namespace std; 9 const int MAXN=1001; 10 inline void read(int &n) 11 { 12 char c='+';bool flag=0;n=0; 13 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;} 14 while(c>='0'&&c<='9')n=n*10+c-48,c=getchar(); 15 } 16 struct E 17 { 18 int u,v,nxt; 19 }edge[MAXN]; 20 int head[MAXN]; 21 int num=1; 22 struct node 23 { 24 int bh; 25 int num; 26 int val; 27 node(){num=0;val=0;} 28 }trie[MAXN]; 29 int tot=0; 30 char a[MAXN]; 31 bool vis[MAXN]; 32 inline void add_edge(int x,int y) 33 { 34 edge[num].u=x; 35 edge[num].v=y; 36 edge[num].nxt=head[x]; 37 head[x]=num++; 38 } 39 long long int ans=0; 40 inline void insert(char *a) 41 { 42 int l=strlen(a);int now=0; 43 for(register int i=0;i<l;i++) 44 { 45 bool flag=0; 46 int debug=a[i]; 47 for(register int j=head[now];j!=-1;j=edge[j].nxt) 48 { 49 if(trie[edge[j].v].val==a[i]) 50 trie[edge[j].v].num++, 51 flag=1, 52 now=edge[j].v; 53 } 54 if(flag==0) 55 { 56 trie[++tot].bh=tot; 57 trie[tot].num=1; 58 trie[tot].val=a[i]; 59 add_edge(now,tot); 60 now=tot; 61 } 62 ans=max(ans,(long long )(i+1)*trie[now].num); 63 } 64 } 65 int main() 66 { 67 memset(head,-1,sizeof(head)); 68 int n; 69 read(n); 70 for(int i=1;i<=n;i++) 71 { 72 memset(a,0,sizeof(a));int hh=0; 73 char ch=getchar();bool flag2=0; 74 while(ch=='\n') ch=getchar(); 75 while(ch!='\n') 76 a[hh++]=ch,ch=getchar(); 77 insert(a); 78 } 79 printf("%lld",ans); 80 return 0; 81 }
然後只好參考別的大神的程式碼.......
編譯速度就秒殺我的程式碼。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 5000010 5 using namespace std; 6 int tot = 1 , head[N] , to[N] , next[N] , cnt , si[N]; 7 char val[N]; 8 void add(int x , int y , char c) 9 { 10 to[++cnt] = y , val[cnt] = c , next[cnt] = head[x] , head[x] = cnt; 11 } 12 int main() 13 { 14 int n , i , j , k , t , p; 15 char ch; 16 long long ans = 0; 17 scanf("%d" , &n); 18 for(i = 1 ; i <= n ; i ++ ) 19 { 20 ch = getchar(); 21 while(ch == '\n') ch = getchar(); 22 for(j = t = 1 ; ch != '\n' ; j ++ , ch = getchar()) 23 { 24 for(p = 0 , k = head[t] ; k ; k = next[k]) 25 { 26 if(val[k] == ch) 27 { 28 p = to[k]; 29 break; 30 } 31 } 32 if(!p) add(t , p = ++tot , ch); 33 t = p , si[t] ++ , ans = max(ans , (long long)j * si[t]); 34 } 35 } 36 printf("%lld\n" , ans); 37 return 0; 38 }