UVALive 6133 Cellphone Typing(字典樹)

題目鏈接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34981

題意:N個單詞的字典,求這N個的單詞的平均敲擊鍵盤的次數,也就是敲擊鍵盤總數/N個單詞。

題解:建字典樹,查詢時遇到分支就加1.

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MAXN = 2000005;
const int MAXM = 30;
char s[MAXN][100];

struct Trie {
    int ch[MAXN][MAXM], val[MAXN];
    int sz;
    void init() {
        sz = 1;
        memset(ch[0], 0, sizeof(ch[0]));
        memset(val, 0, sizeof(val));
    }
    int idx(char c) {
        return c - 'a';
    }
    void insert(char *s) {
        int u = 0, n = strlen(s);
        for (int i = 0; i < n; i++) {
            int c = idx(s[i]);
            if (!ch[u][c]) {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz]++;
                ch[u][c] = sz++;
            } else {
                val[ch[u][c]]++;
            }
            u = ch[u][c];
        }
    }
    int query(char *s) {
        int res = 1;
        int u = 0, n = strlen(s);
        int ls;
        for (int i = 0; i < n; i++) {
            int c = idx(s[i]);
            if (i == 0) {
                ls = val[ch[u][c]];
            } else {
                int cx = val[ch[u][c]];
                if (cx != ls) {
                    res++;
                    ls = cx;
                }
            }
            u = ch[u][c];
            if (ls == 1) {
                break;
            }
        }
        return res;
    }
} AC;

int main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
#endif
    int n;
    while (~scanf("%d", &n)) {
        AC.init();
        for (int i = 1; i <= n; i++) {
            scanf("%s", s[i]);
            AC.insert(s[i]);
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            ans += AC.query(s[i]);
        }
        printf("%.2f\n", ans * 1.0 / (n * 1.0));
    }
    return 0;
}


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