大佬博客:
https://blog.csdn.net/qq_39972971/article/details/80725873
https://blog.csdn.net/oi_Konnyaku/article/details/85805426
https://blog.csdn.net/As_A_Kid/article/details/86286891
http://www.cnblogs.com/zzqsblog/p/6877339.html
zzq大佬的模板应该是最正确的,没有图方便只选之前的一个,但是不知道是否能打破某位大佬所说的:
“请注意,在最优递推式阶数小于等于给定数列长度的一半时,BM算法才能保证求出的递推式最短,否则只能保证求出可行解。”
急,离线等
还没有介绍这是个什么算法呢不过看过这些博客之后也不需要介绍了吧
利用之前的不合法来构造之后的合法,这不失为一种巧妙的构造。
模板:
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
int Pow(int base,int k){
int ret = 1;
for(;k;k>>=1,base=1ll*base*base%mod)
if(k&1)
ret=1ll*ret*base%mod;
return ret;
}
#define vi vector<int>
vi BM(vi arr){
vi now,pre,bst;
int fail,dtfail;
for(int i=0,sz=arr.size();i<sz;i++){
int dt = arr[i];
for(int j=0;j<pre.size();j++) dt = (dt - 1ll * pre[j] * arr[i-j-1]) % mod;
if(!dt) continue;
if(pre.empty()) now.clear() , now.resize(i+1) , fail = i , dtfail = dt;
else{
int K = dt * 1ll * Pow(dtfail,mod-2) % mod;
now.clear() , now.resize(i-fail-1),
now.push_back(K);
for(int j=0;j<bst.size();j++) now.push_back(-K*1ll*bst[j]%mod);
if(now.size()<pre.size()) now.resize(pre.size());
for(int j=0;j<pre.size();j++) now[j] = (now[j] + pre[j]) % mod;
if(i - fail + bst.size() >= pre.size()) bst = pre , fail = i , dtfail = dt;
}
swap(now,pre);
}
return pre;
}
int main(){
int n;
scanf("%d",&n);
vi a;a.resize(n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
vi b = BM(a);
printf("%d\n",b.size());
for(int i=0;i<b.size();i++) printf("%d ",(b[i]+mod)%mod);
}