uva-11732

简单Trie树的应用

val数组是用来表示经过该点的字符串的个数,same表示在该点结束的字符串的个数。主要分三个部分,一个是比当前字符串短的,和当前字符串相同的(注意该种情况下比较的次数位2*(n+1),n是字符串长度,因为最后还要比较‘’),比当前字符串长的。

#include<bits/stdc++.h>
#define _for(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int mod =1e6+7;
double esp=1e-6;
int INF =0x3f3f3f3f;
const int inf = 1<<28;
const int MAXN=5e6+10;
int ch[MAXN][70];
int val[MAXN];
int same[MAXN];
struct Trie
{
    ll ans;
    int sz;
    Trie()
    {
        sz=1;
        memset(ch,0,sizeof(ch));
        memset(val,0,sizeof(val));
        memset(same,0,sizeof(same));
        ans=0;
    }
    int idx(char x)
    {
        if(x>='0'&&x<='9')return x-'0';
        else  if(x>='A'&&x<='Z')return x-'A'+10;
        else if(x>='a'&&x<='z')return x-'a'+36;
    }
    void INSERT(char *s)
    {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int v=idx(s[i]);
            if(ch[u][v]==0)
            {
                ans+=val[u]*(2*i+1);
                ch[u][v]=sz++;
            }
            else
            {
                ans+=(val[u]-val[ch[u][v]])*(2*i+1);
            }
            val[u]++;
            u=ch[u][v];
        }//比当前串短的
        ans+=(same[u]*2*(n+1));//和当前串相同的
        ans+=(val[u]-same[u])*(2*n+1);//比当前串长的
        val[u]++;
        same[u]++;
    }

};
char s[2000];
int main()
{
    int Case=0,t;
    while(~scanf("%d",&t))
    {
        if(t==0)break;
        Trie tmp;
        for(int i=0;i<t;i++)
        {
            scanf("%s",s);
            tmp.INSERT(s);
        }
        printf("Case %d: %lld
",++Case,tmp.ans);
    }
}
原文地址:https://www.cnblogs.com/kayiko/p/12289912.html