【纪中集训2019.3.19】原样输出

题意

描述:

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

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

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

范围:

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

题解:

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

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

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

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

    #include
    #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;
    queueq;
    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=mod)f[x]-=mod;}
          }
          ans=f[1];
      }
      printf("%d\n",ans%mod);
      return 0;
    }

转载于:https://www.cnblogs.com/Paul-Guderian/p/10560514.html

你可能感兴趣的:(【纪中集训2019.3.19】原样输出)