zoukankan      html  css  js  c++  java
  • hihocoder 1457 后缀自动机四·重复旋律7 求不同子串的和

    描述

    小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一段音乐旋律可以被表示为一段数构成的数列。

    神奇的是小Hi发现了一部名字叫《十进制进行曲大全》的作品集,顾名思义,这部作品集里有许多作品,但是所有的作品有一个共同特征:只用了十个音符,所有的音符都表示成0-9的数字。

    现在小Hi想知道这部作品中所有不同的旋律的“和”(也就是把串看成数字,在十进制下的求和,允许有前导0)。答案有可能很大,我们需要对(10^9 + 7)取摸。

    解题方法提示

    输入

    第一行,一个整数N,表示有N部作品。

    接下来N行,每行包含一个由数字0-9构成的字符串S。

    所有字符串长度和不超过 1000000。

    输出

    共一行,一个整数,表示答案 mod (10^9 + 7)。

    Sample Input

    2
    101
    09

    Sample Output

    131

      1 #include<cstring>
      2 #include<cmath>
      3 #include<algorithm>
      4 #include<cstdio>
      5 #include<queue>
      6 #include<iostream>
      7 
      8 #define ll long long
      9 #define N 3000007
     10 #define mod 1000000007
     11 using namespace std;
     12 inline int read()
     13 {
     14     int x=0,f=1;char ch=getchar();
     15     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     16     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 
     20 int n;
     21 struct sam
     22 {
     23     int last,cnt;
     24     int c[N][11],fa[N],mx[N],flag[N];
     25     sam(){last=cnt=1;}
     26     void extend(int x)
     27     {
     28         int p=last,np=last=++cnt;mx[np]=mx[p]+1;
     29         if(x==10)flag[np]=1;
     30         while(p&&!c[p][x])
     31         {
     32             c[p][x]=np;
     33             p=fa[p];
     34         }
     35         if(!p)fa[np]=1;
     36         else
     37         {
     38             int q=c[p][x];
     39             if(mx[q]==mx[p]+1)fa[np]=q;
     40             else
     41             {
     42                 int nq=++cnt;mx[nq]=mx[p]+1;
     43                 memcpy(c[nq],c[q],sizeof(c[q]));
     44                 fa[nq]=fa[q];
     45                 fa[q]=fa[np]=nq;
     46                 while(c[p][x]==q)c[p][x]=nq,p=fa[p];
     47                 if(x==10)flag[nq]=1;
     48             }
     49         }
     50     }
     51     int du[N],num[N];
     52     void init()
     53     {
     54         /*for (int i=1;i<=cnt;i++)
     55         {
     56             for (int j=0;j<=10;j++)
     57                 if(c[i][j])cout<<c[i][j]<<" ";
     58             cout<<endl;
     59         }*/
     60         for (int i=1;i<=cnt;i++)
     61             for (int j=0;j<=10;j++)
     62                 if(c[i][j])du[c[i][j]]++;
     63         num[1]=1;
     64     }
     65     int now,pre;queue<int>q[2];
     66     ll sum[N];
     67     void solve()
     68     {
     69         pre=0,now=1;
     70         for (int i=1;i<=cnt;i++)
     71             if(!du[i])q[pre].push(i);
     72         while(!q[pre].empty())
     73         {
     74             while(!q[pre].empty())
     75             {
     76                 int x=q[pre].front();q[pre].pop();
     77                 if(flag[x])sum[x]=0;
     78                 for (int i=0;i<=10;i++)
     79                     if(c[x][i])
     80                     {
     81                     //    if(c[x][i]==10)cout<<"fack="<<x<<" "<<c[x][i]<<endl;
     82                         if (!flag[x])
     83                         {
     84                             num[c[x][i]]+=num[x];
     85                             (sum[c[x][i]]+=sum[x]*10+num[x]*i)%=mod;
     86                         }
     87                         du[c[x][i]]--;
     88                         if(!du[c[x][i]])q[now].push(c[x][i]);
     89                     }
     90             }
     91             swap(now,pre);
     92         }
     93         /*for (int i=1;i<=cnt;i++)
     94             cout<<sum[i]<<endl;*/
     95         ll ans=0;
     96         for (int i=1;i<=cnt;i++)
     97             (ans+=sum[i])%=mod;
     98         printf("%lld
    ",ans);
     99     }
    100 }sam;
    101 char s[1000007];
    102 
    103 int main()
    104 {
    105     n=read();
    106     for (int i=1;i<=n;i++)
    107     {
    108         scanf("%s",s+1);int len=strlen(s+1);
    109         for (int j=1;j<=len;j++)
    110             sam.extend(s[j]-'0');
    111         if(i<n)sam.extend(10);
    112     }
    113     sam.init();
    114     sam.solve();
    115 }
  • 相关阅读:
    04-增删改查
    03-编写dao实现类方式
    02-基于注解的入门案例
    .net core api 图片上传与加载
    笔记一、数据库初始化 约定
    .net core MVC中级教程(四)
    .net core MVC中级教程(三)
    Windows 盘符映射
    c# 队列和堆栈
    isValidNode
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8531028.html
Copyright © 2011-2022 走看看