AC自动机+DP codeforces86C

版权声明:本文为博主原创文章,转载标明出处。 https://blog.csdn.net/xlzhang223/article/details/82745405

没积分了。。更新一下。。

http://codeforces.com/contest/86/problem/C

AC自动机加DP经典题目,

题意:。。。

思路:构建AC自动机,在AC自动机上跑,这样通过构造可以保证满足条件。再次基础上DP计数,DP[ len ][ idx ][ fail ]

          len 表示 已经走了几步,idx表示在自动机上第几个节点,fail表示已经有几个字母没构成单词。

代码:

#include <bits/stdc++.h>
#define X first
#define Y second
#define MP make_pair
#define PB push_back
#define ll long long
#define pii pair<int,int>
using namespace std;

int n,m;
const int maxn=1005;
const ll mod=1e9+9;
string s;
ll dp[1005][105][15],vis[1005][105][15];//
int nxt[maxn][4],fail[maxn],len[maxn];
int cnt=0;
ll ans=0;
int rev[256];
ll mod_add(const ll &a,const ll &b){
    return (a+b)%mod;
}
void add(string s){
    int node=0;
    for(int i=0;i<s.size();i++){
        if(nxt[node][rev[s[i]]]==0)
            nxt[node][rev[s[i]]]=(++cnt);
        node=nxt[node][rev[s[i]]];
    }
    len[node]=s.size();
}
void get_fail(){
    queue<int> Q;
    for(int i=0;i<4;i++)
        if(nxt[0][i]!=0)Q.push(nxt[0][i]),fail[nxt[0][i]]=0;
    while(!Q.empty()){
        int T=Q.front();
        Q.pop();
        for(int i=0;i<4;i++){
            if(nxt[T][i]==0){
                nxt[T][i]=nxt[fail[T]][i];
                continue;
            }
            int u=nxt[T][i];
            fail[u]=nxt[fail[T]][i];
            len[u]=max(len[u],len[nxt[fail[T]][i]]);//????
            Q.push(u);
        }
    }
}
struct DP{
    int step,idx,wa;
    DP(int x=0,int y=0,int z=0){
        step=x,idx=y,wa=z;
    }
};
void get_ans(){
    queue<DP> Q;
    dp[0][0][0]=1;
    Q.push(DP(0,0,0));
    while(!Q.empty()){
        DP T=Q.front();
        Q.pop();
        for(int i=0;i<4;i++){
            int u=nxt[T.idx][i],f=T.wa+1;
            if(len[u]>=f) f=0;
            dp[T.step+1][u][f]=mod_add(dp[T.step+1][u][f],dp[T.step][T.idx][T.wa]);
            if(T.step+1<n&&f<10&&!vis[T.step+1][u][f])Q.push(DP(T.step+1,u,f)),vis[T.step+1][u][f]=1;
        }
    }
    for(int i=0;i<=cnt;i++) ans=mod_add(ans,dp[n][i][0]);
}
int main(){
    rev['A']=0;rev['C']=1;rev['T']=2;rev['G']=3;
    memset(nxt,0,sizeof(nxt));
    memset(len,0,sizeof(len));
    memset(dp,0,sizeof(dp));
    memset(vis,0,sizeof(vis));
    cin>>n>>m;
    for(int i=0;i<m;i++) cin>>s,add(s);
    get_fail();
    get_ans();
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xlzhang223/article/details/82745405