记录编号 431938 评测结果 AAAAAAAAAA
题目名称 2695.strcmp()函数 最终得分 100
用户昵称 joel 是否通过 通过
代码语言 C++ 运行时间 1.020 s
提交时间 2017-08-02 14:58:35 内存使用 7.07 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int M=1000+10;
class Node//左孩子右兄弟表示法
{
public:
	Node *LeftChild,*RightBrother;
	char c;
	int size;//以当前结点为根的子树上叶节点的个数
	Node():LeftChild(NULL),RightBrother(NULL),c(' '),size(0){}
};
class Trie
{
public:
	Node* root;//根节点
	long long ans;
	Trie():root(NULL),ans(0){}
	
	void INS(Node *p,const char *s)//插入字符串
	{
		int lens=strlen(s);
		Node* v;
		p->size++;//叶子结点数+1
		for(int i=0;i<=lens;i++)//在众多子节点中查找s[i]
		{
			bool found=false;
			for(v=p->LeftChild;v!=NULL;v=v->RightBrother)
				if(v->c==s[i])
				{
					found=true;
					break;
				}
			if(!found)//没有找到建立新节点
			{
				v=new Node;
				v->size=0;
				v->LeftChild=NULL;
				v->RightBrother=p->LeftChild;
				p->LeftChild=v;//成为父节点的第一个孩子
				v->c=s[i];
			}
			p=v;//往下一层走
			p->size++;
		}
	}
	
	void dfs(int depth,Node *p)
	{
		if(p->LeftChild==NULL)//到叶节点时比较结束,比较次数为以叶节点为结束的单词个数x*(x-1)*单词长度
			ans+=p->size*(p->size-1)*depth;
		else
		{
			int sum=0;//sum代表需要比较的单词个数,即叶节点个数
			for(Node* i=p->LeftChild;i!=NULL;i=i->RightBrother)
				sum+=i->size*(p->size - i->size);//每颗子树都要与其他任意一颗子树比较
			ans+=sum/2*(2*depth+1);//因为算了两次所以先/2,每次比较最小代价为2*depth+1
			for(Node* i=p->LeftChild;i!=NULL;i=i->RightBrother)
				dfs(depth+1,i);
		}
	}
	
	long long Count()
	{
		ans=0;
		dfs(0,root);
		return ans;
	}
};
char s[M];
int main()
{
	freopen("strcmp.in","r",stdin);
	freopen("strcmp.out","w",stdout);
	int kase=1,n;
	while(scanf("%d",&n)&&n)
	{
		Trie T;
		T.root=new Node;
		for(int i=1;i<=n;i++)
		{
			scanf("%s",s);
			T.INS(T.root,s);
		}
		printf("Case %d: %lld\n", kase++, T.Count());
	}
	return 0;
}