51nod 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
System Message (题目提供者)
 
 trie树乱搞 
Rank2  实在没法优化了
#include <cstring>
#include <ctype.h>
#include <cstdio>
#define N 1000000
#define BUF 10000010
char real[N];
int ans,Answer,f[N],pos,len,cnt[N],n,trie[N][26],exict[N],siz=1;
char Buf[BUF],*buf=Buf;
inline void Read(int &x)
{
    for(x=0;!isdigit(*buf);++buf);
    for(;isdigit(*buf);x=x*10+*buf-'0',++buf);
}
inline void Readch(char *c)
{
    for(len=0;!islower(*buf);++buf);
    for(;islower(*buf);c[len++]=*buf,++buf);
}
inline void ins(int k,int &p)
{
    if(!p) p=++siz;
    cnt[p]++;
    if(k+1==len) return;
    ins(k+1,trie[p][real[k+1]-'a']);
}
void query(int k,int p)
{
    if(k==len||!p) return;
    if(cnt[p]) ans++,cnt[p]--;
    query(k+1,trie[p][real[k+1]-'a']);
}
inline void write(int now)
{
    if(now>9) write(now/10);
    putchar (now%10+'0');
}
int main()
{
    fread(buf,1,BUF,stdin);
    Read(n);
    for(int i=1;i<=n;++i)
    {
        Readch(real);
        ins(0,trie[1][real[0]-'a']);
    }
    for(pos=1;pos<=n;++pos)
    {
        Readch(real);
        ans=0;
        query(0,trie[1][real[0]-'a']);
        Answer+=ans;
    }
    write(Answer);
    return 0;
}

 

posted @ 2017-08-20 21:54  杀猪状元  阅读(224)  评论(0编辑  收藏  举报