51nod-1526: 分配笔名
【传送门:51nod-1526】
简要题意:
给出n个真名和笔名,都是字符串
要求n个真名和笔名一一匹配,一个真名和一个笔名所带来的价值是这两个字符串的最长公共前缀
题解:
直接将真名和笔名插进字典树里面
d1[i]表示真名在字典树的的第i个点被经过的次数,d2[i]表示笔名在字典树在第i个点经过的次数
将min(d1[i],d2[i])累加就是答案了
可以随意yy一下
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct trie { int c[27]; trie() { memset(c,-1,sizeof(c)); } }t[810000];int tot,d1[810000],d2[810000]; char st[810000]; void clear(int x) { memset(t[x].c,-1,sizeof(t[x].c)); } void bt(int opt) { int len=strlen(st+1),x=0; for(int i=1;i<=len;i++) { int y=st[i]-'a'+1; if(t[x].c[y]==-1) { tot++; clear(tot); t[x].c[y]=tot; } x=t[x].c[y]; if(opt==1) d1[x]++; else d2[x]++; } } int main() { int n; scanf("%d",&n);tot=0; memset(d1,0,sizeof(d1));memset(d2,0,sizeof(d2)); clear(0); for(int i=1;i<=n;i++) scanf("%s",st+1),bt(1); for(int i=1;i<=n;i++) scanf("%s",st+1),bt(2); int ans=0; for(int i=1;i<=tot;i++) ans+=min(d1[i],d2[i]); printf("%d\n",ans); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚