BZOJ 3530: [Sdoi2014]数数 AC自动机+dp

思路不难,但是细节还是挺多的,要格外注意一下. 

code: 

#include <cstdio>  
#include <queue> 
#include <cstring>   
#include <algorithm>  
#define N 2005 
#define ll long long  
#define mod 1000000007    
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
queue<int>q;  
char str[N],S[N];           
int n,m,tot,ch[N][10],f[N],dp[N][N][2],tag[N];  
void insert() 
{
    int i,j,len=strlen(str+1),p=0; 
    for(i=1;i<=len;++i) 
    {     
        if(!ch[p][str[i]-'0']) ch[p][str[i]-'0']=++tot;                
        p=ch[p][str[i]-'0'];        
    }   
    tag[p]=1; 
}         
void build() 
{  
    int i,j;                          
    for(i=0;i<10;++i)  if(ch[0][i])  q.push(ch[0][i]);   
    while(!q.empty()) 
    {
        int u=q.front();q.pop();      
        tag[u]|=tag[f[u]];  
        for(i=0;i<10;++i) 
        {
            int qr=ch[u][i]; 
            if(!qr) { ch[u][i]=ch[f[u]][i]; continue; }   
            f[qr]=ch[f[u]][i];     
            q.push(qr);   
        }
    }
}
int main() 
{ 
    // setIO("input"); 
    int i,j;              
    scanf("%s%d",S+1,&m);  
    n=strlen(S+1); 
    for(i=1;i<=m;++i)  scanf("%s",str+1),insert(); 
    build();             
    for(i=1;i<S[1]-'0';++i) if(!tag[ch[0][i]]) dp[1][ch[0][i]][0]+=1;        
    if(!tag[ch[0][S[1]-'0']])  dp[1][ch[0][S[1]-'0']][1]=1;   
    for(i=1;i<n;++i) 
    {   
        for(j=1;j<10;++j)  if(!tag[ch[0][j]]) dp[i+1][ch[0][j]][0]+=1;        
        for(j=0;j<=tot;++j) 
        {         
            if(tag[j])  continue;    
            if(dp[i][j][0])  
            {   
                for(int k=0;k<10;++k)              
                {
                    if(tag[ch[j][k]]) continue;   
                    (dp[i+1][ch[j][k]][0]+=dp[i][j][0])%=mod; 
                }
            }           
            if(dp[i][j][1]) 
            {          
                for(int k=0;k<S[i+1]-'0';++k)    
                {
                    if(tag[ch[j][k]]) continue;    
                    (dp[i+1][ch[j][k]][0]+=dp[i][j][1]);   
                }
            }  
            if(tag[ch[j][S[i+1]-'0']])   continue;    
            dp[i+1][ch[j][S[i+1]-'0']][1]|=dp[i][j][1];        
        }
    } 
    int ans=0; 
    for(i=0;i<=tot;++i) 
    {
        if(tag[i]) continue;    
        (ans+=dp[n][i][0])%=mod; 
        (ans+=dp[n][i][1])%=mod;     
    }
    printf("%d\n",ans); 
    return 0; 
}

  

上一篇:luogu P3312 [SDOI2014]数表


下一篇:springboot集成rabbitMQ