• 【纪中集训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('
      ');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
      ",ans%mod);
      	return 0;
      }
      
  • 相关阅读:
    常用快捷键
    定时器
    Thread
    io流
    java错误
    Android设置背景图像重复【整理自网络】
    Win7构造wifi热点【Written By KillerLegend】
    Use a layout_width of 0dip instead of wrap_content for better performance.......【Written By KillerLegend】
    关于查看Android系统源码【Written By KillerLegend】
    Android:什么是Holo?【Translated By KillerLegend】
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10560514.html
Copyright © 2020-2023  润新知