LightOJ 1268 Unlucky Strings(KMP+矩阵乘法+基础DP)

题意

给出字符串的长度 \(n\) ,以及该字符串是由哪些小写字母组成,现给出一个坏串 \(S\) ,求存在多少种不同的字符串,使得其子串不含坏串。

\(1 \leq n \leq 10^9\)

\(1 \leq |S| \leq 50\)

思路

矩阵快速幂优化 \(\text{dp}\) 是真的常见,在同层状态数不多,但层数很多的时候,要考虑矩阵快速幂优化 \(\text{dp}\) 。

每一层的状态 \(dp[i]\) 表示匹配到哪里,再枚举给定的字母进行转移,只要不匹配到 \(S\) 结尾都是一个合法的转移,转移系数为 \(1\) 。剩下就是板子了。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
typedef long long LL;
typedef unsigned int uint;
using namespace std;
const int N=53;
struct Matrix
{
    int n,m;uint a[N][N];
    uint *operator [](const int x){return a[x];}
    void resize(int _n,int _m){n=_n,m=_m;}
    Matrix operator *(const Matrix &_)const
    {
        Matrix res;res.resize(n,_.m);
        FOR(i,1,n)FOR(j,1,_.m)
        {
            res[i][j]=0;
            FOR(k,1,m)res[i][j]+=a[i][k]*_.a[k][j];
        }
        return res;
    }
    Matrix operator *=(const Matrix &_){return (*this)=(*this)*_;}
}A,B;
char d_c[30],str[N];
int c_d[256];
int f[N],F[N][30];
int n,m,l;

Matrix Pow(Matrix a,int p)
{
    Matrix res;res.resize(a.n,a.n);
    FOR(i,1,res.n)FOR(j,1,res.n)res[i][j]=(i==j);
    for(;p>0;p>>=1,a*=a)if(p&1)res*=a;
    return res;
}

int main()
{
    int Case;
    scanf("%d",&Case);
    FOR(cas,1,Case)
    {
        scanf("%d",&n);
        scanf("%s",d_c+1);
        scanf("%s",str+1);
        l=strlen(d_c+1);
        m=strlen(str+1);
        FOR(i,1,l)c_d[(int)d_c[i]]=i;

        f[1]=f[2]=1;FOR(i,1,l)F[1][i]=1+(i==c_d[(int)str[1]]);
        FOR(i,2,m)
        {
            f[i+1]=F[f[i]][c_d[(int)str[i]]];
            FOR(j,1,l)
            {
                if(c_d[(int)str[i]]==j)F[i][j]=i+1;
                else F[i][j]=F[f[i]][j];
            }
        }

        A.resize(1,m),B.resize(m,m);
        FOR(i,1,m)A[1][i]=0;
        FOR(i,1,m)FOR(j,1,m)B[i][j]=0;

        A[1][1]=1;
        FOR(i,1,m)FOR(j,1,l)if(F[i][j]<=m)B[i][F[i][j]]++;
        A*=Pow(B,n);
        uint ans=0;
        FOR(i,1,m)ans+=A[1][i];

        printf("Case %d: %u\n",cas,ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Paulliant/p/10205042.html

时间: 2024-10-12 02:42:17

LightOJ 1268 Unlucky Strings(KMP+矩阵乘法+基础DP)的相关文章

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

【bzoj1778】[Usaco2010 Hol]Dotp 驱逐猪猡 矩阵乘法+概率dp+高斯消元

题目描述 奶牛们建立了一个随机化的臭气炸弹来驱逐猪猡.猪猡的文明包含1到N (2 <= N <= 300)一共N个猪城.这些城市由M (1 <= M <= 44,850)条由两个不同端点A_j和B_j (1 <= A_j<= N; 1 <= B_j <= N)表示的双向道路连接.保证城市1至少连接一个其它的城市.一开始臭气弹会被放在城市1.每个小时(包括第一个小时),它有P/Q (1 <= P <=1,000,000; 1 <= Q <

形态形成场(矩阵乘法优化dp)

形态形成场(矩阵乘法优化dp) 短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 \(A=12312301231230,B=1231230,C=123\).现在对于给定的替换式,求字符 AA 所代表的串有多少子串满足: 这个子串为单个字符\(0\)或没有前导\(0\). 把这个子串看作一个十进制数后模\(n\)等于\(0\). 答案对\(r\)取模.对于100%的数据,$2 \l

BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串全部由0~9组成,给出一个串s,求一个长度为n的串,不包含s的种类有多少. 分析 第一眼以为是组合.然后更滑稽的是用错误的方法手算样例居然算出来是对的...我数学是有多差... 题解也是看了好半天,有点难理解. 感觉PoPoQQQ神犇讲得还是比较清楚的.传送门:http://blog.csdn.net/popoqqq/article/details/40188173 我们用dp[

[BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

BZOJ 1875 SDOI 2009 HH去散步 矩阵乘法优化DP

题目大意:给出一张无向图,求从A到B走k步(不能走回头路)的方案数.(k <= 2^30) 思路:看到k的范围就知道是矩阵乘法了.关键是不能走回头路怎么构造.正常的方法构造点的转移不能避免这个问题,就用边来构造.只要保证不经过自己^1的边就可以保证不走回头路了. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX

矩阵乘法优化dp

前几天学姐说要给我们考矩乘dp和期望dp...其实我们都(也可能只有我)不会. 那只能现学了,然而学了一天突然通知不考了qwq 矩阵乘法 A矩阵为m*k,B矩阵为k*n,两矩阵相乘则得C矩阵为m*n; for (int i=1;i<=M;++i) for (int j=1;j<=N;++j) for (int k=1;k<=K;++k) c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod; 矩阵乘法模板  时间复杂度为$O(N^3)$,数学一本通上

算法提高 矩阵乘法 区间dp

问题描述 有n个矩阵,大小分别为a0*a1, a1*a2, a2*a3, ..., a[n-1]*a[n],现要将它们依次相乘,只能使用结合率,求最少需要多少次运算. 两个大小分别为p*q和q*r的矩阵相乘时的运算次数计为p*q*r. 输入格式 输入的第一行包含一个整数n,表示矩阵的个数. 第二行包含n+1个数,表示给定的矩阵. 输出格式 输出一个整数,表示最少的运算次数. 样例输入 3 1 10 5 20 样例输出 150 数据规模和约定 1<=n<=1000, 1<=ai<=1

蓝桥杯基础练习---矩阵乘法

基础练习 矩阵乘法 时间限制:1.0s   内存限制:512.0MB 锦囊1 锦囊2 锦囊3 问题描述 给定一个N阶矩阵A,输出A的M次幂(M是非负整数) 例如: A = 1 2 3 4 A的2次幂 7 10 15 22 输入格式 第一行是一个正整数N.M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数 接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值 输出格式 输出共N行,每行N个整数,表示A的M次幂所对应的矩阵.相邻的数之间用一个空格隔开 样例