• 【BZOJ4641】基因改造 KMP


    【BZOJ4641】基因改造

    Description

    "人类智慧的冰峰,只有萌萌哒的我寂寞地守望。"
    --TB
    TB正走在改造人类智慧基因的路上。TB发现人类智慧基因一点也不萌萌哒,导致人类普遍智商过低,为了拯救低智商人群,博爱的TB开始改造人类智慧基因。人类智慧DNA由C种人类智慧脱氧核苷酸构成(这是一种十分特殊的DNA)。TB智慧DNA片段T长度为M,她可以把另一段长度为M的人类智慧DNA片段S改造成T。改造过程中,TB可以充分发挥智慧,将任意两种人类智慧脱氧核苷酸交换(比如对于片段S=12321,交换1和2变成S=21312,交换1和4变成42324),可以无限次交换。如果S可以通过若干次交换变成T,那么就称S为"萌萌哒人类基因片段"。TB想知道对于一个长度为N的人类智慧DNA片段S[1~N],有多少个长度为M的连续子片段S[i~i+M-1],是"萌萌哒人类基因片段",并且这些"萌萌哒人类基因片段"在哪里。

    Input

    输入文件的第一行包含两个正整数case和C,分别表示数据组数和人类智慧脱氧核苷酸的种数。
    接下来3*case行,每三行表示一组数据:
    第一行一个正整数N和M,表示人类智慧DNA片段S和TB智慧DNA片段T的长度。
    第二行N个正整数,表示人类智慧DNA片段S。
    第三行M个正整数,表示TB智慧DNA片段T。
    对于所有数据数据,case=3, n,m,C<=1000000

    Output

    对于每组数据:
    第一行一个正整数tot,表示"萌萌哒人类基因片段"的个数。
    接下来一行tot个用空格隔开的正整数pos,表示"萌萌哒人类基因片段"开头所在的位置。要求从小到大输出每个pos。

    Sample Input

    3 3
    6 3
    1 2 1 2 3 2
    3 1 3
    6 3
    1 2 1 2 1 2
    3 1 3
    6 3
    1 1 2 1 2 1
    3 1 3

    Sample Output

    3
    1 2 4
    4
    1 2 3 4
    3
    2 3 4
    对于第一组数据:
    S[1~3]=121,可以先将1和2交换变成212,再将2和3交换变成313。
    S[2~4]=212,可以将2和3交换变成313。
    S[4~6]=232,可以先将2和3交换变成323,再将1和2交换变成313。

    题解:这种题多做做就差不多能掌握套路了。

    显然我们将KMP的比较函数改一改即可,不难想到用pre[i],即i上一次出现的位置来当做判相等的条件。特别地,如果pre[i]超出了S与T匹配的范围,则我们视为pre[i]=-1。细节还是需要注意一下的~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    const int maxn=1000010;
    int cas,n,m,C,tot;
    int next[maxn],p1[maxn],p2[maxn],pos[maxn],last[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void work()
    {
    	n=rd(),m=rd(),tot=0;
    	int i,j,a;
    	memset(last,-1,sizeof(last));
    	for(i=0;i<n;i++)	a=rd(),p1[i]=(last[a]==-1)?-1:i-last[a],last[a]=i;
    	memset(last,-1,sizeof(last));
    	for(i=0;i<m;i++)	a=rd(),p2[i]=(last[a]==-1)?-1:i-last[a],last[a]=i;
    	next[0]=-1,i=0,j=-1;
    	p1[n]=p2[m]=0;
    	while(i<m)
    	{
    		if(j==-1||p2[i]==p2[j]||(p2[i]>j&&p2[j]==-1))	next[++i]=++j;
    		else	j=next[j];
    	}
    	i=j=0;
    	while(i<n)
    	{
    		if(j==-1||p1[i]==p2[j]||(p1[i]>j&&p2[j]==-1))	i++,j++;
    		else	j=next[j];
    		if(j==m)	pos[++tot]=i-m+1;
    	}
    	printf("%d
    ",tot);
    	for(i=1;i<=tot;i++)	printf("%d ",pos[i]);
    	printf("
    ");
    }
    int main()
    {
    	cas=rd(),C=rd();
    	while(cas--)	work();
    	return 0;
    }//3 3 6 3 1 2 1 2 3 2 3 1 3 6 3 1 2 1 2 1 2 3 1 3 6 3 1 1 2 1 2 1 3 1 3

     

  • 相关阅读:
    68
    56
    Django manager 命令笔记
    Django 执行 manage 命令方式
    Django 连接 Mysql (8.0.16) 失败
    Python django 安装 mysqlclient 失败
    H.264 SODB RBSP EBSP的区别
    FFmpeg—— Bitstream Filters 作用
    MySQL 远程连接问题 (Windows Server)
    MySQL 笔记
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7670080.html
Copyright © 2020-2023  润新知