zoukankan      html  css  js  c++  java
  • HDU-4436 str2int 后缀自动机

    HDU-4436 str2int

    题意

    (n)个数字串(s_1,s_2,dots,s_n),问有多少个不同的数字(没有前导零)是这(n)个数字串中任意一个的子串,求出这些数字的和对2012取模。

    (nle 10^4,sum_{i=1}^{n} |s_i|le 10^5)

    分析

    (n)个串用一个没出现过的字符连接起来建后缀自动机,后缀自动机上不同路径数即为不同的子串个数,拓扑排序维护答案即可。

    Code

    #include<bits/stdc++.h>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=2e5+10;
    const int inf=1e9;
    int T,n,m;
    char s[N];
    struct SAM{
        int last,cnt;int ch[N][11],fa[N],len[N],sum[N],id[N];
        ll g[N],s[N];
        int newnode(){
            ++cnt;
            for(int i=0;i<11;i++) ch[cnt][i]=0;
            return cnt;
        }
        void insert(int c){
            int p=last,np=newnode();last=np;len[np]=len[p]+1;
            for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
            if(!p) fa[np]=1;
            else {
                int q=ch[p][c];
                if(len[q]==len[p]+1) fa[np]=q;
                else{
                    int nq=newnode();len[nq]=len[p]+1;
                    memcpy(ch[nq],ch[q],sizeof ch[q]);
                    fa[nq]=fa[q],fa[q]=fa[np]=nq;
                    for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
                }
            }
        }
        void init(){
            last=cnt=1;
            for(int i=0;i<11;i++) ch[cnt][i]=0;
        }
        ll solve(){
            ll ans=0;
            rep(i,1,cnt) g[i]=s[i]=sum[i]=0;
            rep(i,1,cnt) sum[len[i]]++;
            rep(i,1,cnt) sum[i]+=sum[i-1];
            rep(i,1,cnt) id[sum[len[i]]--]=i;
            s[1]=1;
            rep(i,1,cnt){
                int u=id[i];
                ans=(ans+g[u])%2012;
                for(int j=(u==1);j<10;j++) if(ch[u][j]){
                    int x=ch[u][j];
                    g[x]=(g[x]+g[u]*10+s[u]*j)%2012;
                    s[x]=(s[x]+s[u])%2012;
                }
            }
            return ans;
        }
    }sam;
    int main(){
        while(~scanf("%d",&m)){
            sam.init();
            for(int i=1;i<=m;i++){
                scanf("%s",s+1);
                int len=strlen(s+1);
                rep(j,1,len) sam.insert(s[j]-'0');
                sam.insert(10);
            }
            printf("%lld
    ",sam.solve());
        }
        return 0;
    }
    
  • 相关阅读:
    DOM元素的位置、尺寸及更多的信息
    BASE1(matlab)
    安装 sublime package control
    php 排序
    highstock
    html5 压缩图片 上传
    2016012016+小学四则运算练习软件项目报告
    构建之法初次阅读之1,2,16章
    一段异步操作的代码(清理缓存)
    计算两点距离 ios
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13929504.html
Copyright © 2011-2022 走看看