BZOJ 1009 [GT 考试]

题面

题意

  给出长度为 \(m\) 的字符串 \(S\),求长度为 \(n\) 不包含 \(S\) 的字符串数量,对 \(k\) 取模。

题解

  考虑用行向量 \(A\) 表示字符串匹配情况,\(A_i\) 表示当前匹配到第 \(i\) 位的字符串数量,那么每次新加一位都可以看作将 \(A\) 右乘一个 \(m \times m\) 的转移矩阵 \(M\)\(M_{i,j} \; (0 \le i < m,0 \le j \le m)\) 代表匹配到第 \(i\) 位的字符串后接 \(ch\) 后恰好匹配到第 \(j\) 位的 \(ch\) 的数量,同时为了让已经匹配完的串不影响其他位置上的匹配情况,让 \(M\) 的第 \(n\) 行全为 \(0\)。可以用 KMP 算法解出 \(M\),但因为 \(m\) 很小,也可以暴力求解。

  这样,由于初始状态下只有匹配到第 \(0\) 位一种情况, 令初始的 \(A\) 除了\(A_0=1\) 以外所有位置都为 \(0\),这样 \(A \cdot M^n\) 所得的行向量的第 \(i\) 位就是长度为 \(n\) 的串中恰好匹配到第 \(i\) 位的串数。可以用矩阵快速幂加速运算,也可以发现 \(A \cdot M^n\) 就是 \(M\) 的第一行。


代码

#include
#include
#include
using namespace std;
const int maxn=25,alpha=11;
int mod;
struct matrix{
    int a[maxn][maxn];
    matrix(){
        memset(a,0,sizeof(a));
    }
};
matrix operator * (const matrix &a,const matrix &b){
    matrix c;
    int i,j,k;
    for (i=0;i>=1;
    }
    return ans;
}
matrix qpow(matrix a,int b){
    matrix ans;
    int i;
    for (i=0;i>=1;
    }
    return ans;
}
int main(){
    int i,n,m,ans;
    matrix tmp;
    scanf("%d%d%d",&n,&m,&mod);
    scanf("%s",s);
    tmp=qpow(solve(m),n);
    ans=0;
    for (i=0;i

你可能感兴趣的:(BZOJ 1009 [GT 考试])