首页 > 代码库 > Light OJ 1268 Unlucky Strings 矩阵快速幂+KMP
Light OJ 1268 Unlucky Strings 矩阵快速幂+KMP
题目来源:Light OJ 1268 Unlucky Strings
题意:给你一些可以用的字符 然后求组成不包含给定字符串的方案数
思路:矩阵经典问题 从i走k步路到达j的方案数 可以用矩阵快速幂求解
对于求长度为n的字符的方案数 就是走n步路 求走法
可以用KMP求出走一步 从前i个字符到前j个字符的方案数 这点有点不好理解 想一想
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int maxn = 55; typedef unsigned int LL; struct Mat { LL a[maxn][maxn]; }; Mat A, B; int f[maxn]; void getFail(char *p) { int m = strlen(p); f[0] = f[1] = 0; for(int i = 1; i < m; i++) { int j = f[i]; while(j && p[i] != p[j]) j = f[j]; f[i+1] = p[i] == p[j] ? j+1 : 0; } } void find(int i, char c, char* p) { int j = i; while(j && c != p[j]) j = f[j]; if(c == p[j]) j++; A.a[i][j]++; } Mat get(Mat x, Mat y, int l) { Mat z; memset(z.a, 0, sizeof(z.a)); for(int i = 0; i < l; i++) for(int j = 0; j < l; j++) for(int k = 0; k < l; k++) { z.a[i][j] += x.a[i][k]*y.a[k][j]; //z.a[i][j] %= mod; } return z; } void Mat_pow(int n, int l) { if(n <= 0) return; while(n) { if(n&1) B = get(A, B, l); A = get(A, A, l); n >>= 1; } } int main() { int cas = 1; int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); char s1[55], s2[55]; scanf("%s %s", s1, s2); getFail(s2); memset(A.a, 0, sizeof(A.a)); memset(B.a, 0, sizeof(B.a)); int l1 = strlen(s1); int l2 = strlen(s2); for(int i = 0; i < l2; i++) { for(int j = 0; j < l1; j++) { find(i, s1[j], s2); } B.a[i][i] = 1; } Mat_pow(n, l2); LL ans = 0; for(int i = 0; i < l2; i++) ans += B.a[0][i]; printf("Case %d: %u\n", cas++, ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。