BZOJ 1009 GT考试(ac自动机+矩阵DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1009

题意:给定一个长度为m的串s。有多少种长度为n的串不包含s?

思路:(1)将s插入trie建立ac自动机。(2)以自动机中的状态作为节点,建立矩阵A[i][j],A[i][j]=1表示j节点为合法状态,也就是能向j转移。(3)计算ans=A^n,则ans=sum(ans[0][i])。

 
 
 
struct node
{
    int next[10],fail,flag;
 
    void init()
    {
        clr(next,0);
        fail=-1;
        flag=0;
    }
};
 
node a[N];
int e,n,m,K;
char s[N];
 

void insert(char s[])
{
    int i,k,p=0;
    for(i=0;s[i];i++)
    {
        k=s[i]-'0';
        if(a[p].next[k]==0)
        {
            a[e].init();
            a[p].next[k]=e++;
        }
        p=a[p].next[k];
    }
    a[p].flag=1;
}
 
queue<int> Q;
 
void build()
{
    Q.push(0);
    int i,j,k,p,q;
    while(!Q.empty())
    {
        k=Q.front();
        Q.pop();
        for(i=0;i<10;i++)
        {
            if(a[k].next[i])
            {
                p=a[k].next[i];
                q=a[k].fail;
                while(q!=-1&&!a[q].next[i]) q=a[q].fail;
                if(q==-1) a[p].fail=0;
                else
                {
                    a[p].fail=a[q].next[i];
                    a[p].flag|=a[a[p].fail].flag;
                }
                Q.push(p);
            }
            else
            {
                q=a[k].fail;
                while(q!=-1&&!a[q].next[i]) q=a[q].fail;
                if(q==-1) a[k].next[i]=0;
                else a[k].next[i]=a[q].next[i];
            }
        }
    }
}
 

class Matrix
{
public:
    u64 a[N][N];
 
    void init(int x)
    {
        clr(a,0);
        int i;
        if(x==1)
        {
            FOR0(i,e) a[i][i]=1;
        }
    }
 
    Matrix operator*(Matrix a)
    {
        Matrix ans,p=*this;
        ans.init(0);
        int i,j,k;
        FOR0(k,e) FOR0(i,e) FOR0(j,e)
        {
            ans.a[i][j]+=p.a[i][k]*a.a[k][j];
            ans.a[i][j]%=K;
        }
        return ans;
    }
 
    Matrix Pow(int n)
    {
        Matrix ans,p=*this;
        ans.init(1);
        while(n)
        {
            if(n&1) ans=ans*p;
            p=p*p;
            n>>=1;
        }
        return ans;
    }
};
 
Matrix p;
 
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    a[0].init();e=1;
    RD(s),insert(s);
    int i,j,k;
    build(); p.init(0);
    FOR0(i,e) if(!a[i].flag) FOR0(j,10)
    {
        k=a[i].next[j];
        if(!a[k].flag) p.a[i][k]++;
    }
    p=p.Pow(n);
    u64 ans=0;
    FOR0(i,e) ans=(ans+p.a[0][i])%K;
    PR(ans);
    return 0;
}

你可能感兴趣的:(AC自动机)