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<iostream>
#include<cstdio>
#include<cstring>
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<maxn;i++) for (j=0;j<maxn;j++) for (k=0;k<maxn;k++)
        c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
    return c;
}
char s[maxn];
int nxt[maxn],to[maxn][alpha];
inline int id(char ch){
    return ch-'0';
}
matrix solve(int n){
    matrix a;
    int i,j,u,v,w;
    nxt[0]=-1;
    for (i=1;i<=n;i++){
        u=nxt[i-1];
        while (~u&&s[i-1]!=s[u]) u=nxt[u];
        nxt[i]=u+1;
    }
    for (i=0;i<n;i++) for (j=0;j<10;j++){
        if (id(s[i])==j) to[i][j]=i+1;
        else to[i][j]=(~nxt[i])?to[nxt[i]][j]:0;
        a.a[i][to[i][j]]++;
    }
    return a;
}
int qpow(int a,int b){
    int ans=1;
    while (b){
        if (b&1) ans=ans*a%mod;
        a=a*a%mod; b>>=1;
    }
    return ans;
}
matrix qpow(matrix a,int b){
    matrix ans;
    int i;
    for (i=0;i<maxn;i++) ans.a[i][i]=1;
    while (b){
        if (b&1) ans=ans*a;
        a=a*a; b>>=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<m;i++) ans+=tmp.a[0][i];
    printf("%d\n",ans%mod);
    return 0;
}
posted @ 2019-12-13 22:58  Kilo-5723  阅读(106)  评论(0)    收藏  举报