hdu4080 Stammering Aliens(二分+字符串hash)

来源:互联网 发布:有道词典的网络设置 编辑:程序博客网 时间:2024/05/29 03:12

题目:

在一个字符串中,找出出现次数不小于m次的最长的子串。
输出最长的子串长度和最右边一个子串的起始位置。

分析:

字符串hash可做。
二分子串的长度,然后处理出来所有这个长度的子串的值,排序后找有没有相同的大于等于m个即可。

代码:

#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <set>#include <map>#include <cmath>#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;#define ms(a,b) memset(a,b,sizeof(a))typedef long long ll;typedef unsigned long long ull;const int MAXN=4e4+5;const double EPS=1e-8;const int INF=0x3f3f3f3f;const int base = 163;char s[MAXN];int n,m,pos;ull Hash[MAXN],p[MAXN];typedef struct{    ull x;    int ps;}S;S tmp[MAXN];void makeHash(){        Hash[0] = 0;    p[0] = 1;    for(int i=1;i<=MAXN;i++){        p[i] = p[i-1] * base;    }    for(int i=1;i<=n;i++){        Hash[i] = Hash[i-1] * base + s[i]-'a';    }}ull getHash(int l,int r,ull Hash[]){    return Hash[r] - Hash[l-1] * p[r-l+1];}bool cmp(const S a,const S b){    if(a.x != b.x)  return a.x < b.x;    return a.ps < b.ps;}bool ok(int len){    pos = -1;    int k=0;    for(int i=n-len+1;i>=1;i--){        tmp[k].x = getHash(i,i+len-1,Hash);        tmp[k++].ps = i;    }    sort(tmp,tmp+k,cmp);    int cnt = 1;    if(m==1)    pos = 1;    for(int i=1;i<k;i++){        if(tmp[i].x == tmp[i-1].x){            cnt ++;            if(cnt >= m){                pos = max(pos,tmp[i].ps);            }        }else{            cnt = 1;        }    }    return pos != -1;}int main(){    while(scanf("%d",&m)){        if(m==0)    break;        scanf("%s",s+1);        n = strlen(s+1);        makeHash();        int l=1,r=n,ans=-1,ansp;        pos=-1;        while(l<=r){            int mid = (l+r)/2;            if(ok(mid)){                ans =  mid;                ansp = pos;                l = mid + 1;            }else{                r = mid - 1;            }        }        if(ans == -1){            printf("none\n");        }else{            printf("%d %d\n",ans,ansp-1);        }       }    return 0;}
原创粉丝点击