UVA_11732_“strcmp()” Anyone?

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

附加个前向星式建图

/*
题意: 给出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;
}

 

posted @ 2013-05-06 20:59  小仪在努力~  阅读(318)  评论(0编辑  收藏  举报