Stammering Aliens

2、Stammering Aliens 

(aliens.cpp)

有一个口吃的外星人,说的话里包含很多重复的字符串,比如babab包含两个bab。给定这个外星人说的一句话,找出至少出现m次的最长字符串。

输入格式:

输入包含多组数据。每组数据第一行为整数m,第二行为一个仅包含小写字母的字符串,长度在m~40000之间。输出结束标志为m=0。

输出格式:

对于每组数据,如果不存在,则输出“none”,否则输出两个整数,即最长字符串的长度及其起始位置的最大值(最后一个满足要求的串的起始位置)。

 

Sample Input 

3

baaaababababbababbab

11

baaaababababbababbab

3

cccccc

0

 

Sample Output 

5 12

none

4 2

 字符串hash加速,

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxlen=4e4+5;
const int N=10000007;
int m,first[N+5],next[maxlen],cnt[maxlen],ans,L;
char ch[maxlen];
inline bool  same(int i,int j,int len)
{
    for(register int k=0;k<len;++k){
        if(ch[i+k]!=ch[j+k])return 0;
    }
    return 1;
}
inline int hash(int l,int r){//铏氭寚
    int ans=0;
    for(register int i=l;i<r;i++){
        ans=(ans*31+ch[i]-'a'+1)%N;
    }
    return ans;
}
inline bool judge(int len)
{    
    memset(first,0,sizeof(first));
    memset(next,0,sizeof(next));
    memset(cnt,0,sizeof(cnt));
    bool back=0;
    ans=0;
    int end=L-len+1;//铏氭寚
    for(register int i=1;i<=end;++i){
        int key=hash(i,i+len);
        bool fd=1;
        for(register int j=first[key];j;j=next[j]){
            if( same( i , j , len ) ){
                fd=0;
                cnt[j]++;
            }
            if(cnt[j]>=m){
                if(ans<i)ans=i;
                back=1;
            }
        }
        if(fd){
            next[i]=first[key];
            first[key]=i;
            cnt[i]++;
            if(cnt[i]>=m){
                if(ans<i)ans=i;
                back=1;
            }
        }
    }
    return back;
}
int main()
{
    freopen("aliens.in","r",stdin);
    freopen("aliens.out","w",stdout);
    while(scanf("%d",&m)==1){
        if(!m)break;
            
        scanf("%s",ch+1);
        L=strlen(ch+1);
        if( !judge(1) ){
            printf("none\n");
            continue;
        }
        int left=0,right=L+1;
        int mid=(left+right)>>1;
        while(left<right-1){
            //printf("l=%d r=%d\n",left,right);
            //printf("%d ",judge(mid));
            if(judge(mid))left=mid;
            else right=mid;
            mid=(right+left)>>1;
        }
        if(judge(right))printf("%d %d\n",right,ans-1);
        else if(judge(left))printf("%d %d\n",left,ans-1);
            else printf("none\n");
    }
    return 0;
}

posted @ 2019-03-24 17:19  Tj1  阅读(208)  评论(0编辑  收藏  举报