• + 1 comment

    let L be the smallest integer such that 2^(L-1) > n/2, L = floor(log(n)+1). the words have repeating patterns that do not exceed L in length.

    O(n*l + m*l) pass all test no timeout

    long alienLanguages(int n, int m) {
        if (n == 1) return 1;
        int L = floor(log(n) / log(2) + 1);
        vector<long> wordsTotal = { 1, n - n / 2 }, prefixTotal = { 0, n - n / 2, 0 };
        vector<vector<long>> prefix(L + 1, vector<long>(n / 2 + 2));
        for (int i = n / 2; i >= 1; i--) {
            prefix[2][i] = min(n - 2 * i + 1, n - n / 2);
            prefixTotal[2] = (prefixTotal[2] + prefix[2][i]) % mod;
        }
        for (int l = 3; l <= L; l++) {
            prefixTotal.push_back(0);
            for (int i = floor(n / pow(2, l - 1)); i >= 1; i--) {
                prefix[l][i] = (prefix[l][i + 1] + prefix[l - 1][2 * i] + prefix[l - 1][2 * i + 1]) % mod;
                prefixTotal[l] = (prefixTotal[l] + prefix[l][i]) % mod;
            }
        }
        for (int l = 2; l <= m; l++) {
            wordsTotal.push_back(0);
            for (int k = 1; k <= min(l, L); k++) wordsTotal[l] = (wordsTotal[l] + prefixTotal[k] * wordsTotal[l - k]) % mod;
        }
        return wordsTotal.back();
    }