【题意】给出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);
    }
}