[51nod 1587]半现串
来源:互联网 发布:arp scan python 编辑:程序博客网 时间:2024/04/30 04:41
题目大意
有两个串S,T。T的长度是d。我们说T在S中半现的条件是当T的某一个长度为 ⌊d/2⌋ 的子串是S的一个子串。(子串是在原串中连续出现的一段字符串)。
现在给定一个原串s,另外给出x,y,他们都只包含数字字符,问区间[x,y]中在s中半现的数字有多少个。
经典套路
先转化为补集问题。
将S所有长度为d/2的串弄个AC自动机,然后做数位DP,f[i,j]表示做到第i位匹配到状态j。
匹配成功状态不要转移。
#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"); }*/}
0 0
- [51nod 1587]半现串
- [51nod 1587]半现串
- [51Nod 1587] 半现串
- 51Nod
- 51Nod
- 51nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- 51Nod
- spring
- angular.js初始化命令 ng-init,ng-bind
- 2016—迷茫的研究生生活
- C# 多线程 简单的同步售票系统代码
- 案例二 树中两个结点的最低公共祖先
- [51nod 1587]半现串
- storm基础篇(1)
- 特征价格(Hedonic price)
- strcpy,sprintf,memcpy的区别
- 数据库的基本操作
- LeetCode #210 - Course Schedule II - Medium
- 机器学习-常见的数据预处理
- SQL 注入利用与防御
- 关于安卓反编译的几种方式(初识)