• SGU142 Keyword好题


    给出一个长度为N的串S(N≤500000)。这个串只包含“a”“b”两种字母。 

    找一个长度为L的串T也是右“a”“b”两种字母组成使得该串不是串S的
    子串且长度L尽可能小。

    问题分析
    这是一道统计的题目。由于串只由两种字母组成因此相当于一个01串。
    如果我们求出S的所有子串然后标记起来再由小到大枚举T串直到T串
    不是S的子串那么就能得出解了。然而S的子串是十分多的所以我们有必
    要分析一下这道题的特征。
    题目要我们使长度L尽可能小。而对于某一个L串S中最多包含N-L+1
    个长度为L的子串。而长度为L的串一共有2L个。若N-L+1<2L则必有某个长
    度为L的串T不是S的子串。而N≤500000因此N-19+1<219所以无论如何L=19必定是一个可行的L。因此我们只需对长度不超过19的子串进行统计。题
    目的规模就大大减小了。
    先将S转成用01串表示。并建立一个Mark数组统计所有长度为1~19的
    串是否是S的子串。对于S的第i位它单独可以构成一个长度为1的子串Q1
    我们把Mark[1,f(Q1)]置为True。它和第i+1位可以构成一个长度为2的子串Q2我们把Mark[2,f(Q2)]置为True。如此下去只需一直处理到第i位和它后面的18位构成一个长度为19的串Q19我们把Mark[19,f(Q19)]置为True。其中f(Qk)表示01串Qk所对应的十进制数。 这样对于每一位都只是处理19次。时间复杂度是O(N)的。而每一位i只与
    它后面的18位发生联系因此存储上可以只开一个1..19的数组空间复杂度是
    O(Log2N)的。
    处理完每一位之后我们就可以由小到大枚举串T如果发现它的Mark是
    False的表示它不是S的子串可以直接输出解。

    #include<cstdlib>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<map>
    #include<algorithm>
    #include<set>
    #include<vector>
    #define LL long long
    #define inf 0x7fffffff
    #define E 1e-9
    #define M 2520
    #define N 500005
    using namespace std;
    int n,k,t;
    bool ma[20][524288];
    bool a[N];
    
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("ex.in","r",stdin);
    #endif
    
        scanf("%d%*c",&n);
        for(int i=0;i<n;i++)
        {
            char c;
            scanf("%c",&c);
            a[i]=c=='a'?0:1;
        }
        for (int i=0;i<n;++i )
        	{
        	    int x=0;
        	    for(int j=i;j<n&&j<i+19;j++)
        	    {
        	        x=x*2+a[j];
        	        ma[j-i+1][x]=1;
        	    }
        	}
        	int flag=1,x,num;
        	for(int i=1;i<20&&flag;i++)
        	{
        	    for(int j=0;j<(1<<i);j++)
        	    {
        	        if(!ma[i][j])
        	        {
        	            num=i;
        	            x=j;
        	            flag=0;
        	            break;
        	        }
        	    }
        	}
            printf("%d\n",num);
            char str[20];
            int i=0;
            while(x)
            {
                str[i++]=x%2;
                x/=2;
            }
            for(int j=0;j<num-i;j++)
            printf("a");
            for(i--;i>=0;i--)
            printf("%c",str[i]==1?'b':'a');
    
        return 0;
    }
    

      

  • 相关阅读:
    BZOJ1001 BJOI2006 狼抓兔子
    NOI2015 程序自动分析
    高斯消元法
    [POJ] 3666 Making the Grade
    [CODEVS] 2185 最长公共上升子序列
    [模板] LIS
    [CF] 219D Choosing Capital for Treeland
    [POJ] 2823 Sliding Window
    [BZOJ] 1072 [SCOI2007]排列perm
    [POJ] 1094 Sorting It All Out
  • 原文地址:https://www.cnblogs.com/sbaof/p/2764587.html
Copyright © 2020-2023  润新知