zoukankan      html  css  js  c++  java
  • HDU 4622 Reincarnation (后缀自动机)

    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.

    InputThe 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.OutputFor 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
    
    题意是求[l,r]的区间里有多少个子串,因为字符串的长度范围很小,我们可以将每个后缀分别放入自动机中预处理。
    然后节点p的贡献就是p->step-p->link->step;
    就能算出当前子串的贡献
    代码如下:
    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    
    using namespace std;
    const int N=2200;
    typedef long long ll;
    ll num;
    ll ans[N][N];
    char A[N];
    struct State
    {
        State *link,*go[26];
        int step;
        int maxx;
        void clear()
        {
            maxx=0;
            link=0;
            step=0;
            memset(go,0,sizeof(go));
        }
        int gx()
        {
          if(link==NULL)return 0;
          return step-link->step;
        }
    }*root,*last;
    int cnt[N];
    int lenA;
    State statePool[N*2],*b[N*2],*cur;
    
    void init()
    {
        cur=statePool;
        root=last=cur++;
        root->clear();
    }
    
    void Insert(int w)
    {
        State *p=last;
        State *np=cur++;
        np->clear();
        np->step=p->step+1;
        while(p&&!p->go[w])
            p->go[w]=np,p=p->link;
        if(p==0){
            np->link=root;
            num+=np->gx();
        }
        else
        {
            State *q=p->go[w];
            if(p->step+1==q->step){
                np->link=q;
                num+=np->gx();
            }
            else
            {
                State *nq=cur++;
                nq->clear();
                memcpy(nq->go,q->go,sizeof(q->go));
                num-=q->gx();
                nq->step=p->step+1;
                nq->link=q->link;
                q->link=nq;
                np->link=nq;
                num+=q->gx()+nq->gx()+np->gx();
                while(p&&p->go[w]==q)
                    p->go[w]=nq, p=p->link;
            }
        }
        last=np;
    }
    void solve()
    {
       for(int i=0;i<lenA;i++)
       {
           num=0;
           init();
           for(int j=i;j<lenA;j++)
           {
              Insert(A[j]-'a');
              ans[i][j]=num;
           }
       }
    }
    int main()
    {
        int t,q,l,r;
        scanf("%d",&t);
        while(t--)
        {
            memset(ans,0,sizeof(ans));
          scanf("%s",A);
          lenA=strlen(A);
          solve();
          scanf("%d",&q);
          while(q--)
          {
              scanf("%d%d",&l,&r);
              printf("%lld
    ",ans[l-1][r-1]);
          }
         }
        return 0;
    }


  • 相关阅读:
    javascript推荐书籍
    [zt]介绍一本搜索引擎爬虫方面的好书
    一些文章资源和趣闻
    【详细的英语自学指导】黑猫出版社 Easyreads系列13本书,科普英语,入门好选择
    网上邻居疑难问题分析与总结
    关于文件夹权限的十个问答
    net send命令解析
    如何成为一名黑客
    全球最值得模仿的230个网站
    女生最爱不释手的30个网站
  • 原文地址:https://www.cnblogs.com/a249189046/p/7705521.html
Copyright © 2011-2022 走看看