_bzoj1009 [HNOI2008]GT考试【矩阵加速dp】

本文介绍了一种使用矩阵快速幂方法解决字符串匹配问题的方法。通过定义状态f(i,j)来表示考号匹配到第i位,且后j位与不吉利串的前j位相匹配的情况,并利用矩阵加速计算过程。

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1009

比较不错的一道题,令f(i, j)表示考号匹配到i位,后j位为不吉利串的前j位,那么对于每一个状态,都是上一个状态的线性组合,所以可以用矩阵来加速。

#include <cstdio>
#include <cstring>

const int maxn = 1000000005, maxm = 25;

int n, m, p, mtx[maxm][maxm], trie[maxm][10], fail[maxm], trans[maxm][maxm], tem[maxm][maxm], ans;
char unf[maxm];

inline void mul(int aa[maxm][maxm], int ss[maxm][maxm]) {
	memset((void*)tem, 0, sizeof tem);
	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < m; ++j) {
			for (int k = 0; k < m; ++k) {
				tem[i][j] = (tem[i][j] + aa[i][k] * ss[k][j]) % p;
			}
		}
	}
	memcpy((void*)aa, (void*)tem, sizeof tem);
}
inline void poww(int mi) {
	int i;
	for (i = 31; mi >> i & 1 ^ 1; --i);
	memcpy((void*)trans, (void*)mtx, sizeof mtx);
	for (--i; ~i; --i) {
		mul(trans, trans);
		if (mi >> i & 1) {
			mul(trans, mtx);
		}
	}
}

int main(void) {
	//freopen("in.txt", "r", stdin);
	scanf("%d%d%d", &n, &m, &p);
	scanf("%s", unf + 1);
	for (int i = 0; i < m; ++i) {
		trie[i][unf[i + 1] - '0'] = i + 1;
	}
	for (int i = 1; i <= m; ++i) {
		for (int j = 0; j < 10; ++j) {
			if (trie[i][j]) {
				fail[trie[i][j]] = trie[fail[i]][j];
			}
			else {
				trie[i][j] = trie[fail[i]][j];
			}
		}
	}
	for (int i = 0; i < m; ++i) {
		for (int j = 0; j < 10; ++j) {
			++mtx[i][trie[i][j]];
		}
	}
	
	poww(n);
	for (int i = 0; i < m; ++i) {
		ans = (ans + trans[0][i]) % p;
	}
	printf("%d\n", ans);
	return 0;
}

  

 

转载于:https://www.cnblogs.com/ciao-sora/p/6193922.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值