1526 分配 笔名
题解
题目来源:
CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 320
难度:7级算法题
收藏
关注
班里有n个同学。老师为他们选了n个笔名。现在要把这些笔名分配给每一个同学,每一个同学分配到一个笔名,每一个笔名必须分配给某个同学。现在定义笔名和真名之间的相关度是他们之间的最长公共前缀。设笔名为a,真名为b,则他们之间的相关度为lcp(a,b)。那么我们就可以得到匹配的质量是每一个同学笔名和真名之间相关度的和。
现在要求分配笔名,使得匹配质量最大。
样例解释:
· bill → bilbo (lcp = 3)
· galya → galadriel (lcp = 3)
· gennady → gendalf (lcp = 3)
· toshik → torin (lcp = 2)
· boris → smaug (lcp = 0)
Input
单组测试数据。 第一行有一个整数n (1≤n≤100000),表示班级中同学的数目。 接下来n行,表示每一个同学的真名,每一个名字是非空串,且由小写字母组成。 名字可能重复。 最后n行是老师已经安排好的笔名。每一个笔名是一个非空串,且由小写字母组成。 笔名可能重复。 输入的字符总数目不超过 800000。
Output
输出最大的匹配质量。
Input示例
样例输入1 5 gennady galya boris bill toshik bilbo torin gendalf smaug galadriel
Output示例
样例输出1 11
1 /* 2 乱搞 3 我们可以先用真名建一颗字典树, 4 然后用笔名在字典树上匹配,标记大于0则 ans++,标记-1 5 不明原理。。。 6 */ 7 #include <cstdio> 8 #include <cstring> 9 10 const int MAXN=1000010; 11 12 char s[MAXN][11],q[MAXN][11]; 13 14 int n,tot,ans; 15 16 int t[MAXN][27],sum[MAXN]; 17 18 inline void build(int cnt) { 19 int now=0; 20 int len=strlen(s[cnt]); 21 for(int i=0;i<len;++i) { 22 int x=s[cnt][i]-'a'+1; 23 if(!t[now][x]) t[now][x]=++tot; 24 now=t[now][x]; 25 ++sum[now]; 26 } 27 return; 28 } 29 30 inline void find(int cnt) { 31 int now=0; 32 int len=strlen(q[cnt]); 33 for(int i=0;i<len;++i) { 34 int x=q[cnt][i]-'a'+1; 35 if(!t[now][x]) break; 36 now=t[now][x]; 37 if(sum[now]) ++ans,--sum[now]; 38 } 39 return; 40 } 41 42 int hh() { 43 scanf("%d",&n); 44 for(int i=1;i<=n;++i) scanf("%s",s[i]),build(i); 45 for(int i=1;i<=n;++i) scanf("%s",q[i]),find(i); 46 printf("%d\n",ans); 47 return 0; 48 } 49 50 int sb=hh(); 51 int main() {;}