码迷,mamicode.com
首页 > 其他好文 > 详细

前缀(字典树)

时间:2015-08-08 22:37:04      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:

  描述:给定N个字符串,求这些字符串的最长公共前缀长度与字符串的个数的乘积的最大值。

   范围:1<=N<=1000000    每个字符串长度小于20000

   样例:

  7

  Jora de Sus
  Orhei
  Jora de Mijloc
  Joreni
  Jora de Jos
  Japca
  Orhejul Vechi

  

  方法一:裸的字典树

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct letter{
 5     char d;//节点存的字符 
 6     int son,bro;//左孩子和右兄弟,都是节点编号 
 7     int cnt;//此节点的孩子个数 
 8 };
 9 
10 char line[30000];
11 int N,best=0,gs=0;
12 letter tr[10000001];
13 
14 void insert(char s[]){
15     int len=strlen(s);//字符串长度,也是字符串在树中的深度 
16     int now=0;//当前节点 
17     
18     for(int i=0;i<len;i++){//i表示深度,深度为0的是root,并不是某字符  
19         tr[now].cnt++;
20         
21         if(tr[now].cnt*i>best)//每一个节点都尝试更新答案 
22             best=tr[now].cnt*i;
23         
24         if(tr[now].son==0){//这个节点没有左孩子 
25             tr[++gs].d=s[i];//插入点 
26             tr[now].son=gs;//让gs为now的左孩子 
27             now=gs;//更行当前节点 
28         }
29         else{
30             now=tr[now].son;
31             while(tr[now].d!=s[i]&&tr[now].bro>0){//找到合适的节点插入 
32                 now=tr[now].bro;
33             }
34             if(tr[now].d!=s[i]){
35                 tr[++gs].d=s[i];
36                 tr[now].bro=gs;
37                 now=gs; 
38             } 
39             
40         }
41     }
42     tr[now].cnt++;
43     
44     if(tr[now].cnt*len>best){//这个更新容易漏掉 
45         best=tr[now].cnt*len;
46     }
47     
48     
49 }
50 
51 int main(){
52     scanf("%d",&N);
53     for(int i=1;i<=N;i++){
54         gets(line);
55         insert(line);
56     }
57     cout<<best;
58     return 0;
59 }

 

前缀(字典树)

标签:

原文地址:http://www.cnblogs.com/CXCXCXC/p/4713946.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!