【纪中集训2019.3.19】原样输出

题意

描述:

​ 给出\(n\)个字符串,你可能会回答两种询问中的一个:

\(k=0\):其中每个串的连续子串拼接起来共有多少个不同的串;

\(k=1\):回答\(k=0\),并且输出所有的子串;

范围:

​ 保证输入不超过\(1 \ M\) ,输出不超过\(200 \ M\)

题解:

  • 对每个串建后缀自动机;

  • 把每个后缀自动机的空节点仿照子序列自动机那样补上;

  • \(dp\)统计答案,\(dfs\)输出方案;

  • 复杂度是\(O(4*n)\)的;

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    const int N=1<<21,mod=1e9+7; 
    int n,k,nxt[4],l[N];
    int cnt,rt[N],len[N],pa[N],ch[N][4],lst,now,L[N],d[N];
    int st[N],top,c[N],f[N],ans;
    queue<int>q;
    char s[N],mp[4]={'A','C','G','T'};
    int get(char x){return x=='A'?0:x=='C'?1:x=='G'?2:3;}
    void extend(int x){
      int p=lst,np=++cnt;lst=np;
      len[np]=len[p]+1;
      while(p&&!ch[p][x])ch[p][x]=np,p=pa[p];
      if(!ch[p][x]){pa[np]=now;return;}
      int q=ch[p][x];
      if(len[q]==len[p]+1){pa[np]=q;return;}
      int nq=++cnt;
      len[nq]=len[p]+1;
      memcpy(ch[nq],ch[q],sizeof(ch[q]));
      pa[nq]=pa[q];pa[q]=pa[np]=nq;
      while(p&&ch[p][x]==q)ch[p][x]=nq,p=pa[p];
    }
    void dfs(int u){
      for(int i=1;i<=top;++i)putchar(mp[st[i]]);
      putchar('\n');ans++;
      for(int i=0;i<4;++i)if(ch[u][i]){
          st[++top]=i;
          dfs(ch[u][i]); 
          --top;
      }
    }
    int main(){
      freopen("copy.in","r",stdin);
      freopen("copy.out","w",stdout);
      scanf("%d",&n);
      for(int i=1;i<=n;++i){
          scanf("%s",s+1);
          l[i]=strlen(s+1);
          rt[i]=now=lst=++cnt;
          for(int j=1;j<=l[i];++j)extend(get(s[j]));
      }
      scanf("%d",&k);
      for(int i=n;i;--i){
          now=rt[i];
          for(int j=now;j<rt[i+1];++j)
          for(int k=0;k<4;++k)if(!ch[j][k])ch[j][k]=nxt[k];
          for(int j=0;j<4;++j)if(ch[now][j])nxt[j]=ch[now][j];
      }
      if(k==1)dfs(1);
      else {
          for(int i=1;i<=cnt;++i)
          for(int j=0;j<4;++j)d[ch[i][j]]++;
          for(int i=1;i<=cnt;++i)if(!d[i])q.push(i),st[++top]=i;
          while(!q.empty()){
              int x=q.front();q.pop();
              for(int i=0;i<4;++i)if(!--d[ch[x][i]])q.push(ch[x][i]),st[++top]=ch[x][i];
          }
          for(int i=cnt,x;i;--i){
              f[x=st[i]]++;
              for(int j=0;j<4;++j)if(ch[x][j]){f[x]+=f[ch[x][j]];if(f[x]>=mod)f[x]-=mod;}
          }
          ans=f[1];
      }
      printf("%d\n",ans%mod);
      return 0;
    }

猜你喜欢

转载自www.cnblogs.com/Paul-Guderian/p/10560514.html
今日推荐