字符串 [SDOI2014]数数

题目描述

 

我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。 给定N和S,计算不大于N的幸运数个数。

输入输出格式

输入格式:

输入的第一行包含整数N。 接下来一行一个整数M,表示S中元素的数量。 接下来M行,每行一个数字串,表示S中的一个元素。

输出格式:

输出一行一个整数,表示答案模109+7的值。

AC自动机+数位DP

怎么解决?

构建Trie图

因为只有在Trie图上才能对答案DP并识别所有的非合法串

DP转移很繁琐

但是还是就那么写

F_{i,j,k}i表示是否顶到上界j为第j位(N)k为第k个节点

特判长度不够的

#include
#include
#include
#include
#include
#include
using namespace std;
const int mod=1e9+7;
const int N=2e4+100;
char C[N];
char S[N];
struct AC_AuTo{
    struct Node{
        int vis[10];
        int end;
        int fail;
    }AC[N];
    /*int cnt;
    inline void Clear(int p){
        AC[p].end=0;
        AC[p].fail=0;
        memset(AC[p].vis,0,sizeof(AC[p].vis));
    }
    inline void Insert(string S){
        int R=S.length();
        int now=0;
        for(int i=0;i Q;
        for(int i=0;i<10;i++){
            if(AC[0].vis[i]){
                AC[AC[0].vis[i]].fail=0;
                Q.push(AC[0].vis[i]);
            }
        }
        while(!Q.empty()){
            int x=Q.front();
            Q.pop();
            for(int i=0;i<10;i++){
                if(AC[x].vis[i]){
                    AC[AC[x].vis[i]].fail=AC[AC[x].fail].vis[i];
                    Q.push(AC[x].vis[i]);
                    AC[AC[x].vis[i]].end|=AC[AC[AC[x].vis[i]].fail].end;
                }
                else AC[x].vis[i]=AC[AC[x].fail].vis[i];
            }
        }
    }*/
    int cnt;
    void Clear(int p){
        AC[p].fail=AC[p].end=0;
        memset(AC[p].vis,0,sizeof(AC[p].vis));
    }
    void Insert(char *S){
        int now=0;
        int len=strlen(S);
        for(int i=0;i Q;
        for(int i=0;i<10;++i){
            if(AC[0].vis[i]){
                AC[AC[0].vis[i]].fail=0;
                Q.push(AC[0].vis[i]);
            }
        }
        while(!Q.empty()){
            int x=Q.front();
            Q.pop();
            for(int i=0;i<10;++i){
                if(AC[x].vis[i]){
                    AC[AC[x].vis[i]].fail=AC[AC[x].fail].vis[i];
                    AC[AC[x].vis[i]].end|=AC[AC[AC[x].fail].vis[i]].end;
                    Q.push(AC[x].vis[i]);
                }
                else AC[x].vis[i]=AC[AC[x].fail].vis[i];
            }
        }
    }
    int F[2][1300][1600];
    int m;
    void Build(){
        cin>>m;
        for(int i=1;i<=m;++i){
            cin>>S;
            Insert(S);
        }
        GetFail();
    }
    void Solve(){
        cin>>(C+1);
        Build();
        int n=strlen(C+1); 
        for(int i=0;i

你可能感兴趣的:(SDOI,2014,动态规划,动态规划,算法)