原题
题目传送
题解
用Trie把所有单词合起来,插入一次就统计一次这个单词和已插入的单词比较的次数。也就是相同部分前缀长度*2+1.但是注意两个完全相同的单词比如说a a需要比4次,因为最后的结束符号也是一样的,还有就是左儿子右兄弟表示法,好好学习QAQ。
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000+10;
const int maxnode=4000000+10;
typedef long long ll;struct Trienode{char ch;int cnt,val;Trienode *lc,*next;Trienode(){lc=next=NULL;val=cnt=ch=0;}
};
struct Trie{Trienode *root;Trie(){root=new Trienode();}inline void clear(){root=new Trienode();}inline ll insert(Trienode *p,char *s,int v){ll ret=0;int n=strlen(s);for(int i=0;i<n;i++){int x=0;Trienode *k=p->lc,*wh=NULL;for(;k;k=k->next){if(k->ch==s[i])wh=k;else x+=k->cnt;}k=wh;if(!k){k=new Trienode();k->next=p->lc;p->lc=k;k->ch=s[i];}if(x) ret=ret+(i*2+1)*x;if(i==n-1) {ret=ret+((i+1)*2+1)*k->cnt;if(k->val) ret+=k->val;}else if(k->val) ret=ret+(2*(i+1)+1)*k->val;k->cnt++;p=k;}p->val+=v;return ret;}
}trie;int kase=0,n;
char s[maxn];
void solve()
{trie.clear();ll ans=0;for(int i=1;i<=n;i++){scanf("%s",s);ans+=trie.insert(trie.root,s,1);}printf("Case %d: %lld\n",++kase,ans);return ;
}int main()
{while(scanf("%d",&n)==1&&n) solve();return 0;
}