la4513 Stammering Aliens 字符串hash

来源:互联网 发布:姓名域名注册 编辑:程序博客网 时间:2024/06/13 21:13

    给一个m和一个字符串,求最长的至少重复出现m次的子串。拿来练练字符串hash了,随然总感觉这种不处理冲突纯拼rp的方法有点不太科学...

做法的话跟后缀数组差不多了,还是二分长度l,去找串中每一个长度为l的子串看出现的次数是否大于等于m,复杂度NlogN.

#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <cstdio>#include <queue>using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn=50000;const int x=123;ull hash[maxn];ull H[maxn];ull xp[maxn];char s[maxn];int rank[maxn];int n,m,p,q,k;inline int idx(char c){    return c-'a';}void hashinit(){    H[n]=0;    for (int i=n-1; i>=0; i--)    {        H[i]=H[i+1]*x+idx(s[i]);    }}int cmp(const int &a,const int &b){    return (hash[a]<hash[b] || (hash[a]==hash[b] && a<b ));}int pos;int check(int l){    for (int i=0; i<n-l+1; i++)    {        rank[i]=i;        hash[i]=H[i]-H[i+l]*xp[l];    }    sort(rank,rank+n-l+1,cmp);//hash第i小的字符串的起点位置    int c=0;    pos=-1;    for (int i=0; i<n-l+1; i++)    {        if (i==0 || hash[rank[i]]!=hash[rank[i-1]]) c=0;        if (++c>=m) pos=max(pos,rank[i]);    }    return pos>=0;}int main(){//    freopen("in.txt","r",stdin);    xp[0]=1;    for (int i=1; i<maxn; i++)    {        xp[i]=xp[i-1]*x;    }    while(~scanf("%d",&m) && m)    {        scanf("%s",s);        n=strlen(s);        hashinit();        int l=1,r=n+1;        int mid;        int ans;        if (check(1)==0)        {            puts("none");            continue;        }        ans=1;        while(l<r)        {            mid=(l+r)>>1;            if (check(mid)) ans=mid,l=mid+1;            else r=mid;        }        check(ans);        printf("%d %d\n",ans,pos);    }    return 0;}


0 0
原创粉丝点击