UVa11732 Strcmp,Anyone?[Trie树]

《UVa11732 Strcmp,Anyone?[Trie树]》
《UVa11732 Strcmp,Anyone?[Trie树]》
题意:给定判断方式和字符串,输出字符串两两比较的次数;
分析:如果使用正常的字典树,空间复杂度为4000*1000*26,果断爆,但我静态数组没有爆反而RE了,不知道为什么,可能UVa没有MLE?等会试一下;然后还会超时,因为每个节点都要枚举,是4000*1000*26*26,,不过机智一点应该不会超时?就每次insert顺便求了。所以,采用树的压缩算法(左孩子右兄弟)。
第一次写多叉转二叉,本来以为会很麻烦,没想到比普通程序还要短一点,所以基本功要练扎实啊,这些都是基础的。
然后就是经验之谈,在明知道不是正解的情况下,尤其是MLE这么一开始就知道的问题,就不要写程序了,免得浪费自己的时间精力和心情。还有就是调试的时候一定要从逻辑入手,数据是弄不完的,太浪费时间了,理一下自己的思路看有哪些特殊情况没有处理,如果还是找不出来问题再自己举特殊例子调。这种类似递推的题一定要把公式的适用情况和逻辑关系理清楚;
程序:

#include<iostream>
    #include<cstdio>
    #include<cstring>
    #define clr(x) memset(x,0,sizeof(x))
    using namespace std;
    const int maxn=4000*1000+5;
    int fr[maxn],tov[maxn],inde,len,n,cnt;
char a[1005],ch[maxn];
long long ans,tot[maxn],sig[maxn];
void init()
{
    ans=0;inde=0;clr(fr);clr(tov);clr(tot);clr(ch);clr(sig);
}
void build(int u,long long dep)
{
    ans+=tot[u]*2LL;
    //ans-=sig[u];
    if(dep==len){
    tot[u]++;
    ans+=sig[u];
    sig[u]++;
    return;}
    tot[u]++;
    for(int i=fr[u];i;i=tov[i])
        if(ch[i]==a[dep]){
        build(i,dep+1);return;}
    tov[++inde]=fr[u];
    fr[u]=inde;
    ch[inde]=a[dep];build(inde,dep+1);
}
int main()
{
    freopen("UVa11732.in","r",stdin);
    freopen("Uva11732.out","w",stdout);
    for(scanf("%d",&n);n;scanf("%d",&n)){
        init();printf("Case %d: ",++cnt);
        for(int i=1;i<=n;i++){
            scanf("%s",a);len=strlen(a);build(0,0);
        }
        printf("%lld\n",ans-tot[0]*(tot[0]-1LL)/2LL);
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/SindarDawn/article/details/52787577
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞