hdu 4758 AC自动机+状压

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yqdjl6/article/details/83184338

这道题卡了好几天,然后发现状态写错的,dp[i][j][k][x]表示走到(i,j)点在AC自动机上第K个点状态为X的步数,有状态K是因为要求必须包含这两种状态,有一点不怎么明白,这道题应该是能用到这两个字符串的方案数,比如说用2.5个第一种和1个第二种这种应该也是可以的。要不然最后统计答案的时候就没法解释了…

#include<bits/stdc++.h>
using namespace std;
using LL = int64_t;
const int maxnode=205;
const int sigma_size=2;
const LL mod=1e9+7;
char s[maxnode];
int dp[105][105][205][4];
struct Node {
    int son[sigma_size];
    int val,fail;
}ch[maxnode];

struct AC {
    int sz=1;
    queue<int>Q;
    void init(int x) {ch[x].fail=ch[x].val=0;memset(ch[x].son,0,sizeof(ch[x].son));}
    int idx(char c) {
        if(c=='D') return 0;
        if(c=='R') return 1;
    }

    void insert(char s[],int v) {
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++) {
            int c=idx(s[i]);
            if(!ch[u].son[c]) {
                init(sz);
                ch[u].son[c]=sz++;
            }
            u=ch[u].son[c];
        }
        ch[u].val=v;
    }

    void build() {
        for(int i=0;i<sigma_size;i++) if(ch[0].son[i]) Q.push(ch[0].son[i]);
        while(!Q.empty()) {
            int now=Q.front();Q.pop();
            int fail=ch[now].fail;
            for(int i=0;i<sigma_size;i++) {
                int nxt=ch[now].son[i];
                if(nxt) {
                    ch[nxt].fail=ch[fail].son[i];
                    Q.push(nxt);
                }
                else ch[now].son[i]=ch[fail].son[i];
                ch[ch[now].son[i]].val|=ch[ch[ch[now].fail].son[i]].val;
            }
        }
    }

    int solve(int n,int m) {
        for(int i=0;i<=n;i++) {
            for(int j=0;j<=m;j++) {
                for(int k=0;k<sz;k++) {
                    for(int x=0;x<=3;x++) {
                        dp[i][j][k][x]=0;
                    }
                }
            }
        }
        dp[0][0][0][0]=1;
        for(int i=0;i<=n;i++) {
            for(int j=0;j<=m;j++) {
                for(int k=0;k<sz;k++) {
                    for(int x=0;x<4;x++) {
                        if(dp[i][j][k][x]>0) {
                            dp[i+1][j][ch[k].son[0]][x|ch[ch[k].son[0]].val]=(dp[i+1][j][ch[k].son[0]][x|ch[ch[k].son[0]].val]+dp[i][j][k][x])%mod;
                            dp[i][j+1][ch[k].son[1]][x|ch[ch[k].son[1]].val]=(dp[i][j+1][ch[k].son[1]][x|ch[ch[k].son[1]].val]+dp[i][j][k][x])%mod;
                        }
                    }
                }
            }
        }
        LL ans=0;
        for(int i=0;i<sz;i++) ans=(ans+dp[n][m][i][3])%mod;
        return ans;
    }

};

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;cin>>T;
    while(T--) {
        AC ans;ans.init(0);
        int n,m;cin>>n>>m;
        cin>>s;ans.insert(s,1);
        cin>>s;ans.insert(s,2);
        ans.build();
        cout<<ans.solve(m,n)<<"\n";
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yqdjl6/article/details/83184338