hdu 4886 TIANKENG’s restaurant(Ⅱ) 字符串

来源:互联网 发布:文章管理系统php源码 编辑:程序博客网 时间:2024/05/18 01:14

题意:

给定一个由A~H8种字符组成,长度不超过1000000的字符串。问在这个字符串的最短不存在连续子串。若存在多个最短连续子串,输出字典序最小的一个。

题解:

先估计最长的答案是多少?我的估计是6个字符长,为什么?长度为6的字符串共有8^6≈250000,如果不存在公用的情况,需要长度250000*6的长度,已经长过1000000了。(有可能是7个字符长的,但7个字符的样例必须考虑字符共用,很难弄出来,所以6个字符就够了,如果想要保证正确性,可以用7个字符的)。

然后找出所有长度小于等于6的所有子串,由于子串是连续的,所以只用6*n的时间去查找。用f[i][j]标记存在的子串,i表示长度,j表示字符的哈希值(字符种类只有8个,用i位8进制就可以表示所有的情况)。最后遍历f数组,找出第一个未被标记的子串即可。



代码:

#include <iostream>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>#include <ctime>#include <vector>#include <cmath>#include <cstdlib>using namespace std;const int maxn=1e6+10;char a[maxn];bool f[6][maxn];int g[10],p[10];void init(){    int i,j,k;    p[0]=1;    for(i=1;i<=6;i++)        p[i]=p[i-1]*8;}void print(int a,int b){    int i,j,k,ans[10];    for(i=0;i<a;i++)    {        ans[i]=b%8;        b=b/8;    }    for(i=a-1;i>=0;i--)        printf("%c",ans[i]+'A');    printf("\n");}int main(){    init();    int T;    scanf("%d",&T);    while(T--)    {        int i,j,k,n;        memset(f,false,sizeof(f));        memset(g,0,sizeof(g));        scanf("%s",a);        n=strlen(a);        //printf("%d\n",n);        for(i=0;i<n;i++)        {            //printf("%d\n",i);            for(j=1;j<=6;j++)            {                g[j]=g[j]*8+(a[i]-'A');                if(i>=j)                {                    g[j]-=(a[i-j]-'A')*p[j];                    f[j-1][g[j]]=true;                    //printf("%d %d\n",j,g[j]);                }                else if(i==j-1)                {                    f[j-1][g[j]]=true;                }                //printf("%d %d\n",j,g[j]);            }        }        for(i=0;i<6;i++)        {            for(j=0;j<p[i+1];j++)                if(!f[i][j])break;            if(j<p[i+1])break;        }        print(i+1,j);    }    return 0;}


0 0
原创粉丝点击