题意:给定n个字符串,问用strcmp函数比较这些字符串共用多少次比较。
分析:
每种情况都要考虑:
1.两串相同时需ans+=(L+1)*2,L为串长度
2.两串中途不同或者一串结束ans+=L*2+1
我是在串插入到树上的过程中,给经过的每个节点加上1,然后之后的串在统计其路径上的1,并且要注意VAL()数组的个数变化,如果数组变小,这说明上一个节点有串结束或者是走到了别的路径去了,这都符合第二种情况。详见代码
#include<iostream> #include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxx=4001*1000+50;
int ch[maxx][80];
int val[maxx];//记录每个节点被经过几次
int pan[maxx];//记录结尾信息
int sz;
void init(){
sz=1;memset(ch[0],0,sizeof(ch[0]));
memset(val,0,sizeof(val));
memset(pan,0,sizeof(pan));
}
int insert(char str[])
{
int res=0;
int u=0,n=strlen(str);
int ji=val[ch[u][str[0]-'0']];
for(int i=0;i<=80;i++)if(ch[u][i]){
if(i==str[0]-'0')continue;
res+=val[ch[u][i]];
}
for(int i=0;i<n;i++)
{
int c=str[i]-'0';
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][c]=sz++;
}
u=ch[u][c];
if(val[u]<ji){//表示在这个节点经过的串数比以前少,可知是有几个串不匹配,故加一
res+=ji-val[u];
ji=val[u];
}
res+=val[u]*2;//现在的节点上有这么多条匹配,故而每一个都有两次比较
val[u]++;
}
res+=val[u]-1+pan[u]; //加上两个串相同时的1和某些比本串长的串的1.
pan[u]++;//结尾标记
return res;
}
char str[1000+50];
int icase=1;
int main(){
long long ans=0;
int n;
while(scanf("%d",&n)==1&&n)
{
ans=0;init();
while(n--)
{
scanf("%s",str);
int aa=insert(str);
ans+=aa;
}
printf("Case %d: %lld\n",icase++,ans);
}
return 0;
}