BM algorithm template

A sequence \ (A [1..n] \) , the shortest \ (F [1..len] \) , such that:
\ (\ I FORALL> len, \ sum_ {J} = ^ {len. 1 } f [j] * a [ ij] = a [i] \)

Assumed to have been determined the \ (a [1..i-1] \) of the recursive shortest \ (F \)

\(∆=a[i]-\sum_{j=1}^{len} f[j]*a[i-j]\)

When \ (Δ = 0 \) , the apparent \ (F \) can be used as \ (a [1..i] \) is recursive, continue

When \ (Δ ≠ 0 \) , we want to find a recursive \ (G \) , so \ (G \) substituting \ (I \) is 1, \ (G \) substituting \ (1 .. i-1 \) is 0, so:
new \ (f '= f + g * Δ \)

There is a mismatch before considering, recursive \ (h0 \) in \ (fail \) at mismatch, and then \ (Δ \) is \ (delta '\) .
Order (H = h0 * X ^ {i-Fail} \) \ , not difficult to find,
1. \ (H substituting the value of i = h0 substituting Fail \) values,
2. \ (H substituting ij (j> 0 ) = H0 value substituted into the value of the fail-j = 0 \)

Then re-enable \ ([i] = h - h [i], h [i-fail] ++ \)

The \ (H \) substituting \ (I \) value = \ ([Delta] '\) , substituting \ (ij (j> 0) \) values \ (= 0 \)

Then \ (f '= f + h * Δ / Δ' \)

\ (H \) of length \ (I-Fail + | H0 | \) , thus maintaining the dynamic \ (i-fail \) minimum mismatch \ (F \) a \ (H0 \) to

Implementation details to note:
1. When first encountered a number 0 ≠, len was assigned 1, need special sentenced
2. Remember to update Fail
3. Scroll to optimize space, see the code to achieve


Template question: https://www.luogu.com.cn/problem/P5487
Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int mo = 998244353;

ll ksm(ll x, ll y) {
	ll s = 1;
	for(; y; y /= 2, x = x * x % mo)
		if(y & 1) s = s * x % mo;
	return s;
}

const int N = 10005;

namespace sub1 {
	ll f[3][N], dta[3];
	int len[3], fail[3];
	void cp(int x, int y) {
		len[y] = len[x]; fail[y] = fail[x]; dta[y] = dta[x];
		fo(i, 1, len[x]) f[y][i] = f[x][i];
	}
	void build(ll *a, int n) {
		fo(i, 0, n) {
			ll d = a[i];
			fo(j, 1, len[0]) d = (d - f[0][j] * a[i - j]) % mo;
			dta[0] = d;
			if(!d) continue;
			fail[0] = i;
			if(!len[0]) {
				cp(0, 1); len[0] = 1;
				continue;
			}
			cp(0, 2);
			ll c = dta[0] * ksm(dta[1], mo - 2) % mo;
			int st = i - fail[1]; len[0] = max(len[0], st + len[1]);
			f[0][st] = (f[0][st] + c) % mo;
			fo(j, 1, len[1]) f[0][st + j] = (f[0][st + j] - c * f[1][j]) % mo;
			if(len[2] - fail[2] < len[1] - fail[1]) cp(2, 1);
		}
	}
}

int n, m; ll a[N];

ll f[N]; int len;

ll x[N], s[N], c[N];

void cheng(ll *a, ll *b) {
	fo(i, 0, 2 * len) c[i] = 0;
	fo(i, 0, len) fo(j, 0, len)
		c[i + j ] = (c[i + j] + a[i] * b[j]) % mo;
	fo(i, 0, 2 * len) a[i] = c[i];
	fd(i, 2 * len, len + 1)	{
		ll v = a[i]; int st = i - (len + 1);
		fo(j, 1, len) a[st + j] = (a[st + j] - v * f[j]) % mo;
	}
}

int main() {
	scanf("%d %d", &n, &m);
	fo(i, 1, n) scanf("%lld", &a[i]);
	sub1 :: build(a, n);
	
	len = sub1 :: len[0];
	fo(i, 1, len) f[i] = sub1 :: f[0][i];
	
	fo(i, 1, len) {
		f[i] = (f[i] % mo + mo) % mo;
		pp("%lld ", f[i]);
	}
	hh;
	
	reverse(f + 1, f + len + 1);
	fo(i, 1, len) f[i] = -f[i]; f[len + 1] = 1;
	
	x[1] = 1; s[0] = 1;
	for(m ++; m; m /= 2, cheng(x, x)) 
		if(m & 1) cheng(s, x);
		
	ll ans = 0;
	fo(i, 1, len) ans = (ans + s[i] * a[i]) % mo;
	pp("%lld\n", (ans % mo + mo) % mo);
}

Guess you like

Origin www.cnblogs.com/coldchair/p/12649835.html