• 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
    ",ans); 
        return 0; 
    }
    

      

  • 相关阅读:
    (转载)C#控件缩写规范
    ToString()格式和用法大全,C#实现保留两位小数的方法
    C#数字前面如何补0
    (转载)C#语言开发规范
    (转载)C#:Enum、Int和String的互相转换,枚举转换
    [踩坑系列]URLEncode 中对 空格的编码有 “+”和“%20”两种
    [IDEA]IDEA设置注释模板
    [Mybatis]Mybatis 常用标签及功能整理
    [设计模式]静态代理
    记一次java电话面试
  • 原文地址:https://www.cnblogs.com/guangheli/p/12088256.html
Copyright © 2020-2023  润新知