【题意】给出strcmp的比较原理,计算要比较所有的字符串需要比较的最少次数。
【解题方法】下面是对that和than这两个单词的比较。
代码中出现了两处比较,因此than和that的比较过程是这样的:
第一步,s[0]和t[0]比较,相同,然后s[0]!=’\0’,又是一次比较,此步共2次;
第二步,s[1]和t[1]比较,相同,然后s[1]!=’\0’,又是一次比较,此步共2次;
第三步,s[2]和t[2]比较,相同,然后s[2]!=’\0’,又是一次比较,此步共2次;
第四步,s[3]和t[3]比较,不相同,不再进行s[i]==’\0’的比较,此步共1次;
综上需要2+2+2+1=7次。
而另外there和the的比较同理,也可以得出7次比较。
一定不能忘记的是,’\0’和’\0’的情况也会比较两次。
因此从这个比较我们容易发现如何维护答案,我们可以变插入变维护答案。但是这个题的字典树是必须用儿子兄弟法表示的,不然会RE。所以借这个题顺便学习了儿子兄弟表示法。【AC 代码】
//File Name: Period.
//Created Author: zxy
//2016/8/1 15:43
//All Rights Reserved.
/************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn=4000010;
ll ans;
char str[4010];
int n,cas;
struct node{
int son[maxn];
int brother[maxn];
int val[maxn];
char ch[maxn];
int sz;
void init(){
sz=1;
ch[0]='#';
son[0]=brother[0]=val[0]=0;
}
void Insert(char *s){
int le=strlen(s),u=0,p;
for(int i=0; i<=le; i++){
//check the brother of u
for(p=son[u]; p; p=brother[p]){
if(ch[p]==s[i]) break;
}
//Can't find so insert
if(!p){
p=sz++;
ch[p]=s[i];
brother[p]=son[u];
son[p]=0;
val[p]=0;
son[u]=p;
}
//更新答案
ans+=(ll)(val[u]-val[p])*(2*i+1);
if(le==i){
//cout<<val[u]<<" "<<val[p]<<endl;
ans+=(ll)(val[p])*(2*i+2);
val[p]++;
}
val[u]++;
u=p;
}
}
}Trie;
int main()
{
int n;
int cas=1;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
Trie.init();
ans=0;
for(int i=0; i<n; i++)
{
scanf("%s",str);
Trie.Insert(str);
}
printf("Case %d: %lld\n",cas++,ans);
}
}