[研究ノート]バーレカンプ・マッセイ

大麦zhenzhendong

週間前のブログが、捨てられた治療の側面を超える指導、そして今日は、彼らが再び祝います。

問題の説明

長さが与えられた\(N- \)は列の数である(\ {a_iを\} \)\、シークA最短線形再帰シーケンス(\ \ {B_i \} \) 設定長さ\(M \)すべてのために)、そのような\(M \のLeq K \ n型のLeq \)がある\(a_k = \ sum_ {iは b_i \) - = 0} ^ M A_ {I kは}

複雑さの要件:\(O(^ N-2)\)

外観は非常に線形再帰消費の定数係数に合います。

アルゴリズムのプロセス

インクリメンタル建設。

我々は現在の計算されたと仮定- (\ A_ {1。0 ... Iを})\線形回帰シーケンス演算処理を、我々が持っていた得た。(C \)\、漸化式を\(I \)で再帰式\(fail_i \)初めて無効ための位置。

始まり\(C = 0 \) 私たちは、空の再帰を持っています。

今、私たちは数追加\(a_iをを\)

セット\(R_C \)の長さ(\ M)\\(= a_iをdelta_i - \ sum_ K = {} 1 A_ ^ {M} I { - } R_C K(K)\)

もし\(delta_i = 0 \) \(R_C \)はまだ正当な再帰的です。

そうでなければ、我々はしたい\(R_C \)新しい再帰的な資格を取得するために調整を行うこと。

もし\(C = 0 \) 最初\(I - 1 \)の数である(0 \)\。我々のみを含む構築する必要が\(I \)を\(0 \)すなわち再帰式ことができます。

場合\(C \ 0 = \) のみ再帰構築する必要が'\(R&LT \) (+ 1 | | R \' \当量のK <N \) 、\(\ I = {sum_を^ {} 1 | R&LT '| {K} A_ - R'_i I} = 0 \)\(\ sum_ 1} ^ {I = {| R&LT' |} N-A_ { - } I = delta_n R'_i \)次いで\(R_ {C + 1} = R_C + Rは、「\) 対象となります。

私達はちょうどC $ <$ 0 \当量のIDを探し 、 そのフロント- \(1 fail_ {ID} \) の数である\(0 \)その上で、我々は変位、すなわち、フロントフィル作る場合。(\ I - fail_ {ID} - 1 \) \(0 \)に続いて、\(1 \)、[接続\( - R_ {ID} \) 我々は唯一の場所を得ることができる(\ I \ )である\(delta_time_unit_addressのID} {} {fail_ \) 残りの位置である)\(0 \アレイ。我々乗算それ全体\(TMP = \ FRAC {delta_ {I}}、{{delta_ fail_ { }}} ID \) 構築した\(R「を\)

すなわち\(R「\)
\ [\ {0,0、... 0 、TMP、-tmp R_ {ID}(1)、 - TMP R_ {ID}(2)、... \} \ ]

その後、我々は確認する必要があります(\ R_C + R」)を\最短で、我々は見つける\(I - fail_上記のid}以上{+ | R_ {上記のid上記} | \) あなたができる最小(ない厳格な証明)

テンプレート

データはビューの週ガイダンスブログのポイントを行くことができます。

#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("");
}

おすすめ

転載: www.cnblogs.com/Vexoben/p/11845379.html