Berlekamp-Massey算法学习小记
程序员文章站
2022-07-12 13:48:32
...
简介
Berlekamp-Massey算法,简称BM算法,可以在时间内求解一个数列的最短线性递推式。
教程
Berlekamp-Massey算法
我们采用增量法构造数列最短线性递推式。
假设现在已经得到了数列的最短线性递推式,且在这之前递推式被修改过次,设第次修改后的递推式为。
如果在加入后原来的递推式仍然满足,也就是有
那么数列的最短线性递推式就是。
不然的话,表明第次修改后的递推式在位置处出错。定义表示第次修改后的递推式在处出错,显然有,同时定义
如果,表明是数列中第一个非零元素,不难证明当前最短线性递推数列就是也就是个。
不然的话,我们可以考虑构造一个新的递推式,若对于任意有
且满足
那么我们只要把和的对应位分别相加就可以得到一个合法的线性递推式。
考虑通过以下方法构造:
设,使,也就是最前面有个,再把数列乘上后接到后面。
为什么这样的是合法的呢?
首先
其次对于所有,设,有
又因为对于数列是一个合法的递推式,故上式等于。
所以新的递推式就是。
代码
这是模1e9+7意义下的版本
(话说最后求出来线性递推式貌似并不是最短的?)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
typedef long long LL;
const int MOD=1000000007;
const int N=3005;
int n,a[N],r[N][N],delta[N],len[N],fail[N];
int ksm(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(LL)ans*x%MOD;
x=(LL)x*x%MOD;y>>=1;
}
return ans;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int cnt=0;
for (int i=1;i<=n;i++)
{
int t=a[i];
for (int j=1;j<=len[cnt];j++) (t+=MOD-(LL)r[cnt][j]*a[i-j]%MOD)%=MOD;
if (!t) continue;
delta[cnt]=t;
fail[cnt]=i;
if (!cnt)
{
len[++cnt]=i;
continue;
}
int mul=(LL)delta[cnt]*ksm(delta[cnt-1],MOD-2)%MOD;
cnt++;
len[cnt]=std::max(len[cnt-1],i-fail[cnt-2]+len[cnt-2]);
for (int j=1;j<=len[cnt-1];j++) r[cnt][j]=r[cnt-1][j];
(r[cnt][i-fail[cnt-2]]+=mul)%=MOD;
for (int j=1;j<=len[cnt-2];j++) (r[cnt][j+i-fail[cnt-2]]+=MOD-(LL)r[cnt-2][j]*mul%MOD)%=MOD;
}
printf("%d\n",len[cnt]);
for (int i=1;i<=len[cnt];i++) printf("%d ",r[cnt][i]);
return 0;
}
上一篇: 阿里云ubuntu下设置程序开机自动启动chkconfig
下一篇: 算法小记