Foj 2299 Prefix(AC自动机、DP)

Foj 2299 Prefix

题意

给定串s、正整数n,问有多少长度为n的字符串t满足:s[0...i]是t的子串,s[0...i+1]不是。

题解

求有多少长度为n的字符串t满足:s[0...i]是t的子串
这样求出来的数列就是答案的一个前缀和。

具体求法可以对于s[0...i]建一个AC自动机,列出dp式子,状态转移矩阵就很好构造了。
现场主要是没想到每个前缀的方案数要分开求。

代码

#include<cstdio>
#include<cmath>
#include<vector>
#include<iostream>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(a) (int)a.size()
#define de(a) cout << #a << " = " << a << endl
#define dd(a) cout << #a << " = " << a << " "
#define all(a) a.begin(), a.end()
#define endl "
"
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

const int N = 22, P = 1e9+7;

int n, m;
int f[N];
string s;

int kpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b&1) res = 1ll*res*a%P;
		a = 1ll*a*a%P;
		b >>= 1;
	}
	return res;
}

inline int add(int a, int b) {
	a+=b;
	if(a>=P) a-=P;
	return a;
}
inline int sub(int a, int b) {
	a-=b;
	if(a<0) a+=P;
	return a;
}
inline int mul(int a, int b) {
	return 1ll*a*b%P;
}

struct Mat {
	static const int N = ::N;
	int a[N][N], n;
	Mat(){} Mat(int _n, int v) { n = _n; rep(i, 0, n) rep(j, 0, n) a[i][j] = i==j ? v : 0; }
	Mat operator * (const Mat &c) const {
		Mat res(n, 0);
		rep(i, 0, n) rep(j, 0, n) rep(k, 0, n) res.a[i][j] = add(res.a[i][j], mul(a[i][k], c.a[k][j]));
		return res;
	}
	Mat operator ^ (int b) const {
		Mat res(n, 1), a = *this;
		while(b) {
			if(b&1) res = res*a;
			a = a*a;
			b>>=1;
		}
		return res;
	}
};
struct Trie {
	static const int N = ::N, M = 26;
	int ne[N][M], fail[N], fa[N], rt, L, ed[N];
	void init() {
		fill_n(ne[fail[0] = N-1], M, 0);
		fill_n(ed, L, 0);
		L = 0;
		rt = newnode();
	}
	int newnode() {
		fill_n(ne[L], M, 0);
		return L++;
	}
	void add(string s) {
		int p = rt;
		rep(i, 0, sz(s)) {
			int c = s[i] - 'A';
			if(!ne[p][c]) ne[p][c] = newnode(), fa[L-1] = p;
			p = ne[p][c];
		}
		ed[p] = 1;
	}
	void build() {
		vi v;v.pb(rt);
		rep(i, 0, sz(v)) {
			int c = v[i];
			rep(i, 0, M) ne[c][i] ? 
				v.pb(ne[c][i]), fail[ne[c][i]] = ne[fail[c]][i] :
				ne[c][i] = ne[fail[c]][i];
		}
	}
	Mat getMat() {
		Mat mat(L, 0);
		rep(i, 0, L) rep(j, 0, M) {
			int nex = ed[i] ? i : ne[i][j];
			++mat.a[i][nex];
		}
		return mat;
	}
}ac;

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);
	int T;
	cin >> T;
	while(T--) {
		cin >> n >> m >> s;
		f[0] = kpow(26, n);
		rep(i, 1, m+1) {
			ac.init();
			ac.add(s.substr(0, i));
			ac.build();
			Mat res = ac.getMat() ^ n;
			f[i] = res.a[0][i];
		}
		rep(i, 0, m) f[i] = sub(f[i], f[i+1]);
		rep(i, 0, m+1) cout << f[i] << endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/wuyuanyuan/p/9220141.html