[UVa 11732] "strcmp()"Anyone?

Link:

UVa 11732 传送门

Solution:

思路还是很套路:建$Trie$树,在$Trie$树上跑一遍统计答案

(统计答案时注意将叶节点特殊处理,同时对于$e(u,v)$用$val[v]*(val[u]-val[v])$来统计个数)

重点在于此题的存储方式:左儿子右兄弟存储法 (链表式存储法)

由于此题节点数$MAXN=4e6$,如果按照$ch[MAXN][27]$建图刚好$MLE$

而链表式存储法优点就在于省空间,不用建立多余的节点,只不过牺牲了查询的效率

实现起来很像链式前向星:$ls[i]$相当于$head[i]$,$rb[i]$相当于$nxt[i]$,每次插入也是从头部插入

Tip:在处理过程中将数据初始化,尽量不用$memset$

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN=4e6+10;
char s[1005],ch[MAXN];ll res=0;
int T,n,ls[MAXN],rb[MAXN],val[MAXN],cnt=0;

void insert()
{
    int len=strlen(s);
    int u=0,v;val[0]++;
    for(int i=0;i<=len;i++)
    {
        bool f=false;
        for(v=ls[u];v;v=rb[v])
            if(ch[v]==s[i]){f=true;break;}
        
        if(!f)
        {
            v=++cnt;ch[v]=s[i]; //建立新节点
            rb[v]=ls[u];ls[u]=v;
            ls[v]=0;val[v]=0;
        }
        u=v;val[u]++;
    }
}

void dfs(int dep,int u)
{
    if(!ls[u]){res+=1ll*val[u]*(val[u]-1)*dep;return;} //统计叶节点的答案
    
    ll sum=0;int v;
    for(v=ls[u];v;v=rb[v]) //统计答案
        sum+=val[v]*(val[u]-val[v]);
    res+=1ll*sum/2*(2*dep+1);
    
    for(v=ls[u];v;v=rb[v])
        dfs(dep+1,v);
}

int main()
{
    while(scanf("%d",&n)==1 && n)
    {
        cnt=0;val[0]=ls[0]=rb[0]=0;
        for(int i=1;i<=n;i++)
            scanf("%s",s),insert();
        
        res=0;dfs(0,0);
        printf("Case %d: %lld\n",++T,res);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/newera/p/9248527.html