[51nod 1587]半现串
2017-01-12 20:26
267 查看
题目描述
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1587AC自动机上的DP
把S所有长度是d/2的提出来造个AC自动机。然后做数位DP,用一维状态表示匹配到AC自动机上哪个节点。
匹配成功状态不要转移。
于是可以计算出不匹配的数量。
#include<cstdio> #include<algorithm> #include<cstring> #define fo(i,a,b) for(i=a;i<=b;i++) #define fd(i,a,b) for(i=a;i>=b;i--) using namespace std; typedef long long ll; const int maxtot=30000+10,mo=1000000007; char s[1200],h[1200]; int g[maxtot][10],next[maxtot][10],fail[maxtot],a[1000],b[1000],c[1000],d[1000],dl[maxtot]; bool bz[maxtot],czy; int f[60][maxtot]; int i,j,k,l,r,t,n,m,tot,root,head,tail,ans,num; char ch; char get(){ char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); return ch; } void insert(int &x,int y){ if (!x) x=++tot; if (y>m/2){ bz[x]=1; return; } insert(g[x][h[y]-'0'],y+1); } void prepare(){ dl[tail=1]=root; fail[root]=root; fo(i,0,9) next[root][i]=root; while (head<tail){ k=dl[++head]; bz[k]|=bz[fail[k]]; fo(i,0,9) if (g[k][i]) next[k][i]=g[k][i];else next[k][i]=next[fail[k]][i]; fo(i,0,9) if (g[k][i]){ if (k==root){ dl[++tail]=g[k][i]; fail[g[k][i]]=root; continue; } j=fail[k]; while (j!=root&&!g[j][i]) j=fail[j]; if (g[j][i]) j=g[j][i]; dl[++tail]=g[k][i]; fail[g[k][i]]=j; } } } void calc(int fh){ fo(i,0,m) fo(j,0,tot) f[i][j]=0; czy=1; t=root; fo(i,0,m-1){ if (czy) fo(j,0,b[i+1]-1) (f[i+1][next[t][j]]+=1)%=mo; t=next[t][b[i+1]]; if (bz[t]) czy=0; fo(j,1,tot){ if (bz[j]) continue; fo(k,0,9) (f[i+1][next[j][k]]+=f[i][j])%=mo; } } if (czy) (f[m][t]+=1)%=mo; fo(i,1,tot) if (!bz[i]) (ans+=f[m][i]*fh)%=mo; } int main(){ //freopen("data.in","r",stdin);//freopen("wzd.out","w",stdout); scanf("%s",s+1); n=strlen(s+1); a[m=1]=get()-'0'; while (1){ ch=getchar(); if (ch<'0'||ch>'9') break; a[++m]=ch-'0'; } fo(i,1,m) b[i]=get()-'0'; fo(i,1,m) c[i]=a[i],d[i]=b[i]; t=1; fd(i,m,1){ if (d[i]<c[i]){ d[i]+=10; d[i-1]--; } (num+=(ll)t*(d[i]-c[i])%mo)%=mo; t=(ll)t*10%mo; } (num+=1)%=mo; root=tot=1; fo(i,1,n-(m/2)+1){ fo(j,i,i+(m/2)-1) h[j-i+1]=s[j]; insert(root,1); } prepare(); calc(1); fo(i,1,m) b[i]=a[i]; b[m]--; i=m; while (b[i]<0){ b[i]+=10; b[i-1]--; i--; } calc(-1); (num-=ans)%=mo; (num+=mo)%=mo; printf("%d\n",num); /*fo(i,1,tot){ fo(j,0,9) printf("%d ",next[i][j]); printf("\n"); }*/ }
相关文章推荐
- 矩阵第二章总结笔记
- 寒假刷题——补模板——写新题
- 7、用滑动条做调色板
- J2EE设计模式
- 洛谷 P1092 虫食算
- fs.inotify.max_user_watches默认值太小,导致too many open files
- zoj2433
- 找出链表的第一个公共结点
- 洛谷 P1255 数楼梯
- Cocos2d-x 3.x 图形学渲染系列十六
- 找出链表的第一个公共结点
- Cocos2d-x 3.x 图形学渲染系列十六
- ajax系列之用jQuery的ajax方法向服务器发出get和post请求
- mybatis实战教程
- RecylerView(GridView布局)实现充值界面效果
- 图的广度优先遍历
- vue项目搭建
- Android API统计
- xml全解析
- dubbo容器