• hdu4622-Reincarnation(后缀自动机)


    Problem Description
    Now you are back,and have a task to do:
    Given you a string s consist of lower-case English letters only,denote f(s) as the number of distinct sub-string of s.
    And you have some query,each time you should calculate f(s[l...r]), s[l...r] means the sub-string of s start from l end at r.
     
    Input
    The first line contains integer T(1<=T<=5), denote the number of the test cases.
    For each test cases,the first line contains a string s(1 <= length of s <= 2000).
    Denote the length of s by n.
    The second line contains an integer Q(1 <= Q <= 10000),denote the number of queries.
    Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n), denote a query.
     
    Output
    For each test cases,for each query,print the answer in one line.
     
    Sample Input
    2
    bbaba
    5
    3 4
    2 2
    2 5
    2 4
    1 4
    baaba
    5
    3 3
    3 4
    1 4
    3 5
    5 5
     
    Sample Output
    3
    1
    7
    5
    8
    1
    3
    8
    5
    1
     
     

    题意: 给一个字符串长度最大2000,给出Q个查询[l,r]包含多少种连续的子串。
    解析: 后缀自动机轻松过,先对查询离线排序,对于左端点相同的建立一个后缀自动
    机,字符串长度最大只有2000,所以最后只用建2000个,每个sam插入的字符最多也就
    2000,时间肯定是够的。

    代码

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=4005;
    struct SAM
    {
        int ch[maxn][26];
        int pre[maxn],step[maxn];
        int last,id;
        void init()
        {
            last=id=0;
            memset(ch[0],-1,sizeof(ch[0]));
            pre[0]=-1; step[0]=0;
        }
        void Insert(int c) //字符转化为数
        {
            int p=last,np=++id;
            step[np]=step[p]+1;
            memset(ch[np],-1,sizeof(ch[np]));
            while(p!=-1&&ch[p][c]==-1)  ch[p][c]=np,p=pre[p];
            if(p==-1) pre[np]=0;
            else
            {
                int q=ch[p][c];
                if(step[q]!=step[p]+1)
                {
                    int nq=++id;
                    memcpy(ch[nq],ch[q],sizeof(ch[q]));
                    step[nq]=step[p]+1;
                    pre[nq]=pre[q];
                    pre[np]=pre[q]=nq;
                    while(p!=-1&&ch[p][c]==q) ch[p][c]=nq,p=pre[p];
                }
                else pre[np]=q;
            }
            last=np;
        }
        int GetCnt()
        {
            int ret=0;
            for(int i=id;i>=1;i--) ret+=step[i]-step[pre[i]];
            return ret;
        }
    }sam;
    char S[maxn/2];
    struct Ques
    {
        int l,r,id;
        Ques(int l=0,int r=0,int id=0):l(l),r(r),id(id){}
        bool operator < (const Ques& t) const
        {
            if(l!=t.l) return l<t.l;
            return r<t.r;
        }
    }q[10005];
    int Q,ans[10005];
    void solve()
    {
        sort(q,q+Q);
        int last;
        for(int i=0;i<Q;i++)
        {
            if(i==0||q[i].l!=q[i-1].l)
            {
                sam.init();
                last=q[i].l;
            }
            for(;last<=q[i].r;last++) sam.Insert(S[last]-'a');
            ans[q[i].id]=sam.GetCnt();
        }
        for(int i=0;i<Q;i++) printf("%d
    ",ans[i]);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",S+1);
            int len=strlen(S);
            scanf("%d",&Q);
            int l,r,id;
            for(int i=0;i<Q;i++)
            {
                scanf("%d%d",&l,&r);
                q[i]=Ques(l,r,i);
            }
            solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Spark Streaming:大规模流式数据处理的新贵
    HBase源码学习系列
    Hadoop源码分析之Configuration
    sql server存储引擎启动错误(SQL Server could not spawn FRunCM thread)
    Redis(1.15)Redis监控(待写)
    Redis(1.14)Redis日常管理与维护
    Redis(1.13)Redis cluster 分布式集群手动配置
    (5.3.5)数据库迁移——数据库与文件组的位置迁移(同一实例)
    Redis(1.12)Redis cluster搭建常见错误
    Redis(1.11)Redis4.0.11 cluster 分布式集群搭建
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5808999.html
Copyright © 2020-2023  润新知