[Study notes] Berlekamp-Massey

barley zhenzhendong

Weeks prior guidance over the side of the blog but abandoned treatment, and today they celebrate again.

Problem Description

Given a length \ (n-\) is the number of columns \ (\ {a_i \} \) , seeking a shortest linear recursion Sequence \ (\ {B_i \} \) (set length \ (m \) ), such that for all \ (m \ Leq K \ n-Leq \) , there are \ (a_k = \ sum_ {i = 0} ^ m a_ {k - i} b_i \)

Complexity Requirements: \ (O (^ n-2) \)

A look very fit with constant coefficients of linear recursion consumption.

Algorithmic process

Incremental Construction.

Suppose we have calculated the current \ (A_ {0 ... I -. 1} \) . The linear recurrence Sequence calculation process, we have obtained had \ (C \) a recursion formula, the \ (I \) a recursive formula in \ (fail_i \) position for the first time ineffective.

Beginning \ (c = 0 \) , we have an empty recursive.

Now we add the number \ (a_i \) .

Set \ (R_c \) length of \ (m \) , \ (= a_i delta_i - \ sum_ K = {}. 1 A_ ^ {m} I {-} R_c K (K) \)

If \ (delta_i = 0 \) , \ (R_c \) is still a legitimate recursive.

Otherwise, we want to \ (R_c \) to make adjustments to get a new recursive qualified.

If \ (C = 0 \) , then the first \ (i - 1 \) number is \ (0 \) we only need to construct comprising a. \ (I \) a \ (0 \) recursive formula i.e. can.

If \ (C \ 0 = Not \) , only need to construct a recursive \ (R & lt '\) , when the \ (| R' | + 1 \ leq k <n \) when, \ (\ I = {sum_ ^ {}. 1 | R & lt '| {K} A_ - R'_i I} = 0 \) , \ (\ sum_. 1} ^ {I = {| R & lt' |} n-A_ {-} I = delta_n R'_i \) , then the \ (R_ {c + 1} = R_c + R '\) becomes eligible.

We just look for a $ 0 \ leq id <c $ , its front \ (fail_ {id} - 1 \) number is \ (0 \) on it if we make a displacement, i.e., the front fill. \ ( i - fail_ {id} - 1 \) a \ (0 \) , followed by a \ (1 \) , and then connect \ (- R_ {ID} \) , we can get only a location \ (I \ ) is \ (delta_time_unit_address ID} {} {fail_ \) , the remaining positions are \ (0 \) of the array. then we multiply it entire \ (tmp = \ frac {delta_ {i}} {delta_ {fail_ { }}} ID \) , to construct a \ (R '\)

I.e. \ (R '\) to
\ [\ {0,0, ... 0 , tmp, -tmp R_ {id} (1), - tmp R_ {id} (2), ... \} \ ]

Then we have to ensure \ (R_c + R '\) is the shortest, we find \ (i - fail_ the above mentioned id} {+ | R_ {the above mentioned id} | \) . The minimum you can (not strict proof)

template

Data can go weeks guidance blog point of view.

#pragma GCC optimize("2,Ofast,inline")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define LL long long
#define pii pair<int, int>
using namespace std;
const int mod = 1e9 + 7;

template <typename T> T read(T &x) {
    int f = 0;
    register char c = getchar();
    while (c > '9' || c < '0') f |= (c == '-'), c = getchar();
    for (x = 0; c >= '0' && c <= '9'; c = getchar())
        x = (x << 3) + (x << 1) + (c ^ 48);
    if (f) x = -x;
    return x;
}

inline void upd(int &x, int y) {
    (x += y) >= mod ? x -= mod : 0;
}

inline int add(int x, int y) {
    return (x += y) >= mod ? x - mod : x;
}

inline int dec(int x, int y) {
    return (x -= y) < 0 ? x + mod : x;
}

inline int Qpow(int x, int p) {
    int ans = 1;
    for (; p; p >>= 1) {
        if (p & 1) ans = 1LL * ans * x % mod;
        x = 1LL * x * x % mod;
    }
    return ans;
}

inline int Inv(int x) {
    return Qpow(x, mod - 2);
}

namespace BM {

    const int Maxn = 5005;
    
    int n, c;
    int a[Maxn], del[Maxn], fail[Maxn];
    vector<int> R[Maxn];

    vector<int> solve() {
        c = 0;
        for (int i = 1; i <= n; ++i) {
            if (c == 0) {
                if (a[i]) {
                    fail[0] = i;
                    ++c;
                    del[i] = a[i];
                    fail[c] = i;
                    R[c].resize(i);
                }
                continue;
            }
            del[i] = a[i];
            for (int j = 0; j < R[c].size(); ++j) {
                del[i] = dec(del[i], 1LL * R[c][j] * a[i - j - 1] % mod);
            }
            if (del[i] == 0) continue;
            fail[c] = i;
            int id = c - 1, v = i - fail[id] + R[id].size();
            for (int j = c - 1; j >= 0; --j) {
                if (v > i - fail[j] + R[j].size()) {
                    v = i - fail[j] + R[j].size();
                    id = j;
                }
            }
            int p = i - fail[id];
            int tmp = 1LL * del[i] * Inv(del[fail[id]]) % mod;
            R[c + 1] = R[c];
            if (R[c + 1].size() < v) R[c + 1].resize(v);
            upd(R[c + 1][p - 1], tmp);
            for (int j = 0; j < R[id].size(); ++j) {
                upd(R[c + 1][p + j], -1LL * tmp * R[id][j] % mod + mod);
            }
            ++c;
        }
        if (c == 0) return vector<int>(0);
        return R[c];
    }
}
using namespace BM;

int main() {
    read(n);
    for (int i = 1; i <= n; ++i) read(a[i]);
    vector<int> ans = BM::solve();
    cout << ans.size() << endl;
    for (int i = 0; i < ans.size(); ++i)
        cout << ans[i] << ' ';
    puts("");
}

Guess you like

Origin www.cnblogs.com/Vexoben/p/11845379.html