字典树;
不过数据量很大;4000*1000;
我用的是传统的方法建树,虽然优化了一下,边插入边统计,不过还是T了;
这是我的代码:
1 #include<cstdio> 2 #include<cstring> 3 #define maxn 4000009 4 using namespace std; 5 int nonocount; 6 long long ans; 7 struct node 8 { 9 int num; 10 node *a[62]; 11 } no[maxn]; 12 13 node* newnode() 14 { 15 node *p=no+nonocount++; 16 p->num=0; 17 memset(p->a,NULL,sizeof p->a); 18 return p; 19 } 20 21 void insert(node *root,char *s) 22 { 23 int l=strlen(s); 24 for(int i=0; i<l; i++) 25 { 26 int x; 27 if(s[i]>='0'&&s[i]<='9')x=s[i]-'0'; 28 else if(s[i]>='a'&&s[i]<='z')x=s[i]-'a'+10; 29 else if(s[i]>='A'&&s[i]<='Z')x=s[i]-'A'+36; 30 if(root->a[x]==NULL) 31 root->a[x]=newnode(); 32 ans+=(root->num)-(root->a[x]->num); 33 root->num++; 34 root=root->a[x]; 35 } 36 } 37 char s[1005]; 38 int main() 39 { 40 int n,ca=1; 41 while(scanf("%d",&n)&&n) 42 { 43 nonocount=0; 44 node *p=newnode(); 45 ans=0; 46 for(int i=0; i<n; i++) 47 { 48 scanf("%s",s); 49 insert(no,s); 50 } 51 printf("Case %d: %lld ",ca++,ans); 52 } 53 return 0; 54 }
网上的大神的方法是采用左儿子右兄弟的方法建树;
这样节省了很多的时间,受教了!
大神的代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxnode = 4000*1000; 7 struct trie 8 { 9 int left[maxnode]; // 左儿子 10 int right[maxnode]; // 右兄弟 11 int val[maxnode] ; //该节点上有多少串 12 char ch[maxnode]; // 节点表示的字符 13 int cnt ; 14 long long int ans ; 15 void init() 16 { 17 ch[0] = 0, left[0] = right[0] = 0; 18 val[0] = 0; 19 cnt = 1; 20 ans = 0; 21 } 22 void insert(const char *s) 23 { 24 int len = strlen(s) , u = 0,j; 25 for(int i = 0; i <= len ; ++i ) 26 { 27 for(j = left[u]; j ; j = right[j])if(ch[j] == s[i]) break; //找到这个节点 28 if(j==0) 29 { 30 j = cnt++; 31 ch[j] = s[i]; 32 right[j] = left[u]; 33 left[j] = 0; 34 left[u] = j; 35 val[j] = 0; 36 } 37 ans += (val[u] - val[j])*(i << 1|1); 38 if(i == len) 39 { 40 ans += val[j]*((i+1)<<1); //特判结尾 Trie中不会进入结尾字符,需特判统计 41 val[j]++; 42 } 43 val[u]++; 44 u = j; 45 } 46 } 47 } Tri; 48 char tmp[2000]; 49 int main() 50 { 51 int n,kase = 1 ; 52 while(scanf("%d",&n)==1 && n) 53 { 54 Tri.init(); 55 for(int k=0; k<n; ++k) 56 { 57 scanf("%s",tmp); 58 Tri.insert(tmp); 59 } 60 printf("Case %d: %lld ", kase++, Tri.ans); 61 } 62 return 0; 63 }