bzoj 3530: [Sdoi2014]数数

来源:互联网 发布:matlab与java混合编程 编辑:程序博客网 时间:2024/05/14 00:35

题意:

求1~n中不含有集合S中的元素为子串,不含前导0。

题解:

一开始傻傻的写了之前的数位dp版本。
换了种打法,f[i][j][k]表示前i位,在自动机j号点上。
k=0为小于n,k=1等于,k=2大于。
然后瞎转移。
code:

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<queue>#include<algorithm>#define LL long longusing namespace std;const int mod=1000000007;struct trnode{    int a[11],fail;    bool tail;    trnode(){tail=false;}}tr[2000];int root=1,tot=1;int f[1210][2000][4];int m,n,a[1210];char s[1510];void build(){    int len=strlen(s+1);    int x=root;    for(int i=1;i<=len;i++)    {        int c=s[i]-'0';        if(tr[x].a[c]) x=tr[x].a[c];        else x=tr[x].a[c]=++tot;    }    tr[x].tail=true;}queue<int> q;void make_root(){    q.push(root);    while(!q.empty())    {        int x=q.front();q.pop();        for(int i=0;i<=9;i++)        {            if(!tr[x].a[i]) continue;            if(x==root) tr[tr[x].a[i]].fail=root;            else            {                int j=tr[x].fail;                while(j!=root&&!tr[j].a[i]) j=tr[j].fail;                tr[tr[x].a[i]].fail=tr[j].a[i];                tr[tr[x].a[i]].tail|=tr[tr[j].a[i]].tail;            }            q.push(tr[x].a[i]);        }    }}int qs(int k,int x){    if(k==x) return 1;    if(k<x) return 0;    return 2;}int main(){    scanf("%s",s+1);    n=strlen(s+1);    for(int i=1;i<=n;i++) a[i]=s[i]-'0';    scanf("%d",&m);    for(int i=0;i<=9;i++) tr[root].a[i]=++tot;    for(int i=1;i<=m;i++)    {        scanf("%s",s+1);        build();    }    make_root();    f[0][root][1]=1;    for(int i=0;i<n;i++)        for(int x=1;x<=tot;x++)            for(int K=0;K<3;K++)            {                if(tr[x].tail||f[i][x][K]==0) continue;                for(int c=0;c<=9;c++)                {                    if(x==root&&c==0) continue;                    int k=x;                    while(!tr[k].a[c]) k=tr[k].fail;                    if(!tr[tr[k].a[c]].tail)                    {                        if(K!=1) (f[i+1][tr[k].a[c]][K]+=f[i][x][K])%=mod;                        else (f[i+1][tr[k].a[c]][qs(c,a[i+1])]+=f[i][x][K])%=mod;                    }                }            }    int ans=0;    for(int i=1;i<=n;i++)        for(int j=2;j<=tot;j++)            for(int k=0;k<=2;k++)                if(k<=1||i!=n) (ans+=f[i][j][k])%=mod;    printf("%d",ans);}
原创粉丝点击