欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

"Strcmp()" Anyone? UVA - 11732

程序员文章站 2022-04-17 14:46:05
...

自己不会写,借用别人的题解,详情点击:题解 , 原题解没有具体的解释,我想强行解释一波"Strcmp()" Anyone? UVA - 11732

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
const int maxn=4000001;
int sz;
int trie[maxn][62],time[maxn],isEnd[maxn];//time[i]=k表示第i个结点经过了k个单词,isEnd[j]=k表示以第j个结点结束的单词有k个
long long ans;
int getId(char c)
{
		if(c>='0'&&c<='9')return c-'0';
		else if(c>='A'&&c<='Z')return c-55;
		else return c-61;
}
void insert(char temp[])
{
	int u=0,id;
	for(int i=0;temp[i];i++)
	{
		id=getId(temp[i]);
		if(!trie[u][id])
		{
			memset(trie[sz],0,sizeof(trie[sz]));
			trie[u][id]=sz++;
			ans+=time[u]*(2*i+1);//这种情况是u结点下有多个子结点,设此时有n个子结点,当出现新的子结点时,
                                             //新的子结点需要与其它n个结点比较,总的比较次数为n*(2*i+1),i为新结点在temp串的位置。
}
		else ans+=(time[u]-time[trie[u][id]])*(2*i+1);//因为一个父结点有许多子结点,所以会出现父子结点出现次数不一致的现象,父结
                                    //出现的次数减去子结点出现的次数(经过父结点出去temp串的串的个数)乘以子结点在temp串的位置就是比较次数。
		time[u]++;
		u=trie[u][id];
	}
	int l=strlen(temp);
	ans+=isEnd[u]*2*(l+1);//出现相同的单词需要比较的次数
	ans+=(time[u]-isEnd[u])*(2*l+1);//一个单词包含在另一个单词里面需要比较的次数。
	time[u]++;
	isEnd[u]++;
}
int main()
{
	int n;
	int cas=1;
	while(scanf("%d",&n)&&n)
	{
		memset(time,0,sizeof(time));
		memset(isEnd,0,sizeof(isEnd));
		char temp[1000];
		memset(trie[0],0,sizeof(trie[0]));
		sz=1;
		ans=0;
		for(int i=0;i<n;i++)
		{
			scanf("%s",temp);
			insert(temp);
		}
		printf("Case %d: %lld\n",cas++,ans);
	}
}