zoukankan      html  css  js  c++  java
  • [51nod1587]半现串

    将s所有长度为d/2的子串放进ac自动机中,直接匹配就可以判定半现串了
    再对其做一个差分,询问一个前缀的半现串个数,在ac自动机上数位dp,f[i][j][0/1]表示走了i步(i位的字符串),走到节点j,是否达到上限的方案数
    对于ac自动机上的结束节点,直接重置并累计答案即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 1005
     4 #define c (s[i]-'0')
     5 #define mod 1000000007
     6 queue<int>q;
     7 int V,n,d,ans,mi[51],mo[51],vis[N*50],nex[N*50],ch[N*50][11],f[51][N*50][2];
     8 char s[N],s1[51],s2[51];
     9 void add(int l,int r){
    10     int k=0;
    11     for(int i=l;i<=r;i++){
    12         if (!ch[k][c])ch[k][c]=++V;
    13         k=ch[k][c];
    14     }
    15     vis[k]=1;
    16 }
    17 void build(){
    18     for(int i=0;i<10;i++)
    19         if (ch[0][i])q.push(ch[0][i]);
    20     while (!q.empty()){
    21         int k=q.front();
    22         q.pop();
    23         for(int i=0;i<10;i++)
    24             if (!ch[k][i])ch[k][i]=ch[nex[k]][i];
    25             else{
    26                 nex[ch[k][i]]=ch[nex[k]][i];
    27                 q.push(ch[k][i]);
    28             }
    29     }
    30 }
    31 int query(char *s){
    32     ans=0;
    33     memset(f,0,sizeof(f));
    34     mi[0]=mo[d]=f[0][0][1]=1;
    35     for(int i=1;i<=d;i++)mi[i]=10LL*mi[i-1]%mod;
    36     for(int i=d-1;i>=0;i--)mo[i]=(mo[i+1]+1LL*c*mi[d-i-1])%mod;
    37     for(int i=0;i<d;i++)
    38         for(int j=0;j<=V;j++){
    39             if (vis[j])continue;
    40             for(int k=0;k<10;k++){
    41                 int p=ch[j][k];
    42                 f[i+1][p][0]=(f[i+1][p][0]+f[i][j][0])%mod;
    43                 if (k<=c)f[i+1][p][k==c]=(f[i+1][p][k==c]+f[i][j][1])%mod;
    44             }
    45         }
    46     for(int i=0;i<=d;i++)
    47         for(int j=0;j<=V;j++)
    48             if (vis[j])
    49                 ans=(ans+1LL*f[i][j][0]*mi[d-i]+1LL*f[i][j][1]*mo[i])%mod;
    50     return ans;
    51 }
    52 int main(){
    53     scanf("%s%s%s",s,s1,s2);
    54     n=strlen(s);
    55     d=strlen(s1);
    56     V=0;
    57     for(int i=0;i<=n-d/2;i++)add(i,i+d/2-1);
    58     build();
    59     ans=(query(s2)-query(s1)+mod)%mod;
    60     for(int i=0,k=0;s1[i];i++){
    61         k=ch[k][s1[i]-'0'];
    62         if (vis[k]){
    63             ans=(ans+1)%mod;
    64             break;
    65         }
    66     }
    67     printf("%d",ans);
    68 }
    View Code
  • 相关阅读:
    高可用Redis(七):Redis持久化
    高可用Redis(六):瑞士军刀之bitmap,HyperLoglog和GEO
    高可用Redis(五):瑞士军刀之慢查询,Pipeline和发布订阅
    高可用Redis(四):列表,集合与有序集合
    高可用Redis(三):Hash类型
    高可用Redis(二):字符串类型
    高可用Redis(一):通用命令,数据结构和内部编码,单线程架构
    详解Django的CSRF认证
    详解MariaDB数据库的事务
    详解MariaDB数据库的触发器
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11629252.html
Copyright © 2011-2022 走看看