UVA_11732_“strcmp()” Anyone?

o(︶︿︶)o 唉,菜鸟整理出来大神的代码~

附加个前向星式建图

UVA_11732_“strcmp()” Anyone?

/*

题意: 给出n个字符串, 计算两两比较的次数. 每次比较都需要比较(str1[i] == str2[i])和 (str1[i] == '\0'各一次).

点评:

将N个字符串插入前缀树,‘\0’也插入,这样就能区分字符串的终结点

S1与S2的共同前缀S,则比较次数为len(S)*2+1

但S1与S2相同,则比较次数为 (len(S1)+1)*2 (注意:这时连'\0’都算进去了噢~,因为适用性,所以模板最好是用一维的前向星式的

*/

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 1005

const int maxnode = 4001*1000+5;

const int sigma_size = 26;

typedef long long ll;

struct Trie

{

    int first[maxnode], next[maxnode]; //前向星式子建图还记得么,亲?

    int total[maxnode], ch[maxnode]; //total[i]记录每个节点被遍历的的次数,ch[i]记录字符串的值的

    int sz;  //记录ch的坐标的

    void clear()

    {

        sz = 1;

        total[0] = first[0] = next[0] = 0;

    }

   

    void insert(const char *s)

    {

        int u = 0, v, n = strlen(s);

        total[u]++;

        for(int i = 0; i <= n; ++i)

        {

            bool flag = false;

            for(v = first[u]; v != 0; v = next[v]) //前向星式遍历

            {

                if(ch[v] == s[i])

                {

                    flag = true;

                    break;

                }

            }

            if( !flag )

            {

                v = sz++; 

                total[v] = 0; //初始化

                ch[v] = s[i];

                next[v] = first[u];

                first[u] = v;

                first[v] = 0;

            }

            u = v;

            total[u]++;

        }

    }

   

    void dfs(int depth, int u, ll &ans)

    {

        if( first[u] == 0 ) ans += total[u]*(total[u]-1)*depth; //如果下面没有节点了,那么ans*=total[u]*(total[u]-1)*depth

        else

        {

            int sum = 0;

            for(int v = first[u]; v != 0; v = next[v])

                sum += total[v]*(total[u]-total[v]);  //否则计算比较次数,当前节点-相同的分支的节点的数量

            ans += (sum/2*(2*depth+1)); 

            for(int v = first[u]; v != 0; v = next[v])

                dfs(depth+1, v, ans);

        }

    }

};

int n;

char str[MAX];

Trie tr;

int main()

{

    int t = 1;

    while(~scanf("%d", &n))

    {

        if(n == 0) break;

       

        tr.clear();

        for(int i = 0; i < n; ++i)

        {

            scanf("%s", str);

            tr.insert(str);

        }

       

        ll ans = 0;

        tr.dfs(0, 0, ans);

        printf("Case %d: %lld\n", t++, ans);

    }

   

    return 0;

}

 

你可能感兴趣的:(uva)