zoukankan      html  css  js  c++  java
  • HDU 4416 Good Article Good sentence (后缀自动机)

     
                                                                                                                                                      Good Article Good sentence
    In middle school, teachers used to encourage us to pick up pretty sentences so that we could apply those sentences in our own articles. One of my classmates ZengXiao Xian, wanted to get sentences which are different from that of others, because he thought the distinct pretty sentences might benefit him a lot to get a high score in his article.
    Assume that all of the sentences came from some articles. ZengXiao Xian intended to pick from Article A. The number of his classmates is n. The i-th classmate picked from Article Bi. Now ZengXiao Xian wants to know how many different sentences she could pick from Article A which don't belong to either of her classmates?Article. To simplify the problem, ZengXiao Xian wants to know how many different strings, which is the substring of string A, but is not substring of either of string Bi. Of course, you will help him, won't you?

    InputThe first line contains an integer T, the number of test data.
    For each test data
    The first line contains an integer meaning the number of classmates.
    The second line is the string A;The next n lines,the ith line input string Bi.
    The length of the string A does not exceed 100,000 characters , The sum of total length of all strings Bi does not exceed 100,000, and assume all string consist only lowercase characters 'a' to 'z'.
    OutputFor each case, print the case number and the number of substrings that ZengXiao Xian can find.
    Sample Input
    3
    2
    abab
    ab
    ba
    1
    aaa
    bbb
    2
    aaaa
    aa
    aaa
    Sample Output
    Case 1: 3
    Case 2: 3
    Case 3: 1

    题意为是第一个串的子串,但不是后面所有串的子串的数量。
    分析:先用第一个串构建后缀自动机,然后让之后每个串都在自动机上跑一遍,记录在每个节点的最大匹配长度
    对于每个节点,它能提供的子串数是p->step-p->link->step。那么现在求满足条件的子串的话,
    可以设maxx为该节点被匹配的最大长度,如果maxx>0,该节点的贡献就是p->step-p->maxx(如果maxx>0那么maxx,必然大于p->link->step)
    如果maxx=0,那么该点贡献为p->step-p->link->step.最后累加即可
    代码如下:
    #include <iostream>
    #include <string.h>
    #include <algorithm>
    #include <stdio.h>
    
    using namespace std;
    const int N=100010;
    typedef long long ll;
    struct State
    {
        State *link,*go[26];
        int step;
        int maxx;
        void clear()
        {
            maxx=0;
            link=0;
            step=0;
            memset(go,0,sizeof(go));
        }
    }*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;
        else
        {
            State *q=p->go[w];
            if(p->step+1==q->step)
                np->link=q;
            else
            {
                State *nq=cur++;
                nq->clear();
                memcpy(nq->go,q->go,sizeof(q->go));
                nq->step=p->step+1;
                nq->link=q->link;
                q->link=nq;
                np->link=nq;
                while(p&&p->go[w]==q)
                    p->go[w]=nq, p=p->link;
            }
        }
        last=np;
    }
    
    void tsort()
    {
        memset(cnt,0,sizeof(cnt));
        State *p;
        for(p=statePool;p!=cur;p++)
          cnt[p->step]++;
        for(int i=1;i<=lenA;i++)
          cnt[i]+=cnt[i-1];
        for(p=statePool;p!=cur;p++)
          b[--cnt[p->step]]=p;
    }
    char A[N],B[N];
    int main()
    {
        int t,n,len1,Case=0;
        scanf("%d",&t);
        while(t--)
        {
            Case++;
          State *p;
          scanf("%d",&n);
          scanf("%s",A);
          lenA=strlen(A);
          init();
          for(int i=0;i<lenA;i++)
            Insert(A[i]-'a');
          tsort();
          while(n--)
          {
             scanf("%s",B);
             int lenB=strlen(B);
             len1=0;
             p=root;
             for(int i=0;i<lenB;i++)
             {
               int x=B[i]-'a';
               if(p->go[x])
               {
                   len1++;
                   p=p->go[x];
               }
               else
               {
                   while(p&&!p->go[x])p=p->link;
                   if(p==NULL)
                   {
                      p=root;
                      len1=0;
                   }
                   else
                   {
                      len1=p->step+1;
                      p=p->go[x];
                   }
               }
                 p->maxx=max(p->maxx,len1);
             }
          }
          int L=cur-statePool;
          ll ans=0;
          for(int i=L-1;i>0;i--)
          {
              p=b[i];
              if(p->maxx>0)
              {
                 ans+=p->step-p->maxx;
                 p->link->maxx=p->link->step;
              }
              else ans+=p->step-p->link->step;
          }
          printf("Case %d: ",Case);
          printf("%lld
    ",ans);
        }
        return 0;
    }


  • 相关阅读:
    淘宝客之 API调用实例讲解
    15个哲理小故事
    淘宝客之 淘宝客类目URL获取
    应广大淘宝客支持者 发布CHM API文档一份 鄙视官方没有离线文档
    淘宝客开发知识 开发前准备与基础知识
    富人和穷人间存在的十二个致命差异
    侧边栏
    半颗星星评分
    让DIV动起来
    软件项目开发过程中主要遇到的核心问题小结
  • 原文地址:https://www.cnblogs.com/a249189046/p/7705023.html
Copyright © 2011-2022 走看看