PowerOJ 1100 最短的名字 字典樹半個模版

在一個奇怪的村子中,很多人的名字都很長,比如aaaaa, bbb and abababab。

名字這麼長,叫全名顯然起來很不方便。所以村民之間一般只叫名字的前綴。比如叫'aaaaa'的時候可以只叫'aaa',因爲沒有第二個人名字的前三個字母是'aaa'。不過你不能叫'a',因爲有兩個人的名字都以'a'開頭。村裏的人都很聰明,他們總是用最短的稱呼叫人。輸入保證村裏不會有一個人的名字是另外一個人名字的前綴(作爲推論,任意兩個人的名字都不會相同)。

如果村裏的某個人要叫所有人的名字(包括他自己),他一共會說多少個字母?
輸入第一行爲數據組數T (T<=10)。每組數據第一行爲一個整數n(1<=n<=1000),即村裏的人數。以下n行每行爲一個人的名字(僅有小寫字母組成)。輸入保證一個村裏所有人名字的長度之和不超過1,000,000。
對於每組數據,輸出所有人名字的字母總數。
1
3
aaaaa
bbb
abababab



字典樹記錄半個模版

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
int name[N][26];
int sz;
int n;
int ans;
char s[100000];
int val[N*10];  ///開到足夠大
void inssert()
{
    int u = 0;
    int len = strlen(s);
    for(int i = 0;i < len;i++){
        int c = s[i]-'a';
        if(!name[u][c]){
            memset(name[sz],0,sizeof name[sz]);
            name[u][c] = sz++;
        }
        val[u]++;
        u = name[u][c];
    }
    val[u]++;
}

void dfs(int u,int dep)
{
    for(int i = 0;i < 26;i++){
        if(name[u][i]){
            int t = name[u][i];
            if(val[t] == 1){
                ans += dep;
                continue;
            }
            dfs(name[u][i],dep+1);
        }
    }
}

int main(void)
{
    int T;
    scanf("%d",&T);
    while(T--){
        sz = 1;  ///置1
        ans = 0;
        memset(name[0],0,sizeof name[0]);
        memset(val,0,sizeof val);
        scanf("%d",&n);
        for(int i = 1;i <= n;i++){
            scanf("%s",s);
            inssert();
        }
        dfs(0,1);
        printf("%d\n",ans);
    }
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章