您的位置:首页 > 其它

[BZOJ 3530][Sdoi 2014]数数

2014-11-17 20:58 387 查看
阿拉~好像最近总是做到 AC 自动机的题目呢喵~

题目的算法似乎马上就能猜到的样子…… AC 自动机 + 数位 dp

先暴力转移出 f[i][j] :表示从 AC 自动机上第 j 号节点走 i 步且不碰到匹配串的方案数

然后直接用数位 dp 一位一位的试就可以了,大家都会吧~

但是…… 有前导 0 的情况真尼玛蛋疼啊!

忽的灵光一闪……

前导 0 仅能影响长度小于 L 的数的统计

那么所有长度 <L 的数全部专门暴力统计一边不就可以了!我真是特么太机智了喵~ O(∩_∩)O~

虽然有个 O(10*L*l) 的转移 但是只跑了 272 ms 呢

#include <cstdio>
#include <cstring>
#define ord(ch) ((ch)-'0')
const int sizeOfLength=1201;
const int sizeOfNumber=1501;
const int sizeOfType=10;
const int mod=1000000007;

struct node
{
int idx;
bool end;
node * fail, * ch[sizeOfType];
};
node * dfa;
node memory[sizeOfNumber], * port=memory;
inline node * newnode();
inline void insert(char * , int);
node * q[sizeOfNumber]; int l, r;
inline void build();
inline void dynamicprogramming();

char N[sizeOfLength]; int L;
int M;
int f[sizeOfLength][sizeOfNumber];
char s[sizeOfNumber]; int len;
inline int getint();
inline int getstr(char * );
inline void putint(int);

int main()
{
int ans=0;
bool find=true;
node * t;

L=getstr(N);
M=getint();
dfa=newnode();
for (int i=1;i<=M;i++)
{
len=getstr(s);
insert(s, len);
}
build();
dynamicprogramming();

t=dfa;
for (int i=0;i<L;i++)
{
for (int j=(i==0);j<ord(N[i]);j++) if (!t->ch[j]->end)
ans=(ans+f[L-i-1][t->ch[j]->idx])%mod;
t=t->ch[ord(N[i])];
if (t->end)
{
find=false;
break;
}
}
for (int i=L-2;i>=0;i--)
for (int j=1;j<=9;j++)
ans=(ans+f[i][dfa->ch[j]->idx])%mod;

putint(ans+find);

return 0;
}
inline int getint()
{
register int num=0;
register char ch;
do ch=getchar(); while (ch<'0' || ch>'9');
do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
return num;
}
inline int getstr(char * str)
{
register int len=0;
register char ch;
do ch=getchar(); while (ch<'0' || ch>'9');
do str[len++]=ch, ch=getchar(); while (ch>='0' && ch<='9');
return len;
}
inline void putint(int num)
{
char stack[11];
register int top=0;
for ( ;num;num/=10) stack[++top]=num%10+'0';
for ( ;top;top--) putchar(stack[top]);
putchar('\n');
}
inline node * newnode()
{
node * ret=port++;
ret->idx=port-memory-1;
ret->fail=NULL;
memset(ret->ch, 0, sizeof ret->ch);
return ret;
}
inline void insert(char * s, int l)
{
node * t=dfa;
for (int i=0;i<l;i++)
{
if (!t->ch[ord(s[i])]) t->ch[ord(s[i])]=newnode();
t=t->ch[ord(s[i])];
}
t->end=true;
}
inline void build()
{
dfa->fail=dfa;
for (int i=0;i<sizeOfType;i++)
if (dfa->ch[i])
{
dfa->ch[i]->fail=dfa;
q[r++]=dfa->ch[i];
}
else
dfa->ch[i]=dfa;
for ( ;l<r;l++)
{
node * u=q[l];
u->end|=u->fail->end;
for (int i=0;i<sizeOfType;i++)
if (u->ch[i])
{
u->ch[i]->fail=u->fail->ch[i];
q[r++]=u->ch[i];
}
else
u->ch[i]=u->fail->ch[i];
}
}
inline void dynamicprogramming()
{
int tot=port-memory;
for (int i=0;i<tot;i++)
if (!(dfa+i)->end)
f[0][(dfa+i)->idx]=1;
for (int i=1;i<=L;i++)
for (int j=0;j<tot;j++) if (!(dfa+j)->end)
for (int k=0;k<sizeOfType;k++)
f[i][(dfa+j)->idx]=(f[i][(dfa+j)->idx]+f[i-1][(dfa+j)->ch[k]->idx])%mod;
}


机房不卡代码插入了 好评如潮
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: