题解思路:用字典树模板加记录一下上一个状态剩余的字母个数
然后进入的个数是v[u]没有进入的个数就是pre[u]
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cctype>
#include<algorithm>
#define mes(s) memset(s,0,sizeof(s))
typedef long long int ll;
using namespace std;
const int mx = 4002*1000;
struct trie{
int ch[mx][63];
int v[mx];
int sum;
int sz;
void init(){ sz = 1, mes(ch[0]),mes(v),sum = 0;}
int idx(char c){
if(isdigit(c))
return c-'0';
else if(islower(c))
return c-'a'+10;
else if(isupper(c))
return c-'A'+36;
else
return 62;
}
void insert(char *s){
int u = 0,len = strlen(s);
sum++;
for(int i = 0; i <= len; i++){
int d = idx(s[i]);
if(!ch[u][d]){
mes(ch[sz]);
ch[u][d] = sz;
sz++;
}
u = ch[u][d];
v[u]++;
}
}
int find(char *s){
int u = 0,len = strlen(s);
int ans = 0;
int pre = sum;
for(int i = 0; i <= len; i++){
int d = idx(s[i]);
if(!ch[u][d])
return ans += pre;
u = ch[u][d];
ans += 2*v[u]; //进入的个数加上判断是否为s[i]是否为'\0'所以次数要乘于2
ans += pre-v[u];
pre = v[u];
}
return ans;
}
}word;
int main(){
int n;
int casei = 1;
char s[2000];
while(cin>>n&&n){
word.init();
ll ans = 0;
for(int i = 1; i <= n; i++){
scanf("%s",s);
ans += word.find(s);
word.insert(s);
}
printf("Case %d: %lld\n",casei++,ans);
}
return 0;
}