UVa 11732 统计使用strcmp()两两比较字符串的总次数 字典树

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2832&mosmsg=Submission+received+with+ID+13213761

P210

注意:字符串的量非常大,用二维的字典树会爆内存

用兄弟节点+儿子节点的字典树以时间换空间

一个节点有子节点和兄弟节点

对于节点u:son[u]为其子节点。

nexts[u] 为u的兄弟节点(相当于一个单链表)

 

 

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
#define ll long long
#define maxnode 4000010
ll ans;
struct Trie  
{  
    char ch[maxnode];  
    int son[maxnode],nexts[maxnode],size;  
    int Have_word[maxnode];  
	int val[maxnode];
	void init(){
		size = 1;
		memset(son, 0, sizeof(son)); memset(nexts, 0, sizeof(nexts)); memset(ch, 0, sizeof(ch)); memset(Have_word, 0, sizeof(Have_word)); memset(val, 0, sizeof(val)); 
	}
	void insert(char *s){
		int u = 0, v, len = strlen(s);
		for(int i = 0; i <= len; i++)
		{
			bool find = false, big = false;
			for(v = son[u]; v; v = nexts[v])
				if(ch[v] == s[i]){ find = true;	break; }

			if(find == false)
			{
				v = size++;
				nexts[v] = son[u];
				son[u] = v;
				ch[v] = s[i];
			}
			ans += (val[u]-val[v])*(i<<1|1);
			if(i == len)
			{ ans+=val[v]*((i+1)<<1); val[v]++; }
			val[u]++;
			u = v;
		}
		Have_word[u]++;
	}  
}ac;  
int n;
char s[1005];
int main(){
	int Cas = 1;
	while(scanf("%d",&n), n){
		ac.init();
		ans = 0;
		while(n--)
		{
			scanf("%s",s);
			ac.insert(s);
		}
		printf("Case %d: %lld\n",Cas++,ans);
	}
}
/*
2
0
0
3
sadf156A
aAS
05sf4s5dfS
3
aZZ
AZZ
AZZ
3
AZZ
AZZ
aZZ
4
ABCD
ABC
ABCD
ABD

2
abcd
abc

*/


 

你可能感兴趣的:(UVa 11732 统计使用strcmp()两两比较字符串的总次数 字典树)