4.2美团笔试题4(哈希 二分)

4.2美团笔试题4(哈希 二分)_第1张图片

解析:

先哈希处理。(判断子串是否相同)

然后枚举两个位置 i , j i,j i,j,代表ABA中两个A的起点是i和j。

首先 [ i , i + k − 1 ] [i,i+k-1] [i,i+k1] [ j , j + k − 1 ] [j,j+k-1] [j,j+k1]要相同,然后二分找到最大的L使得 [ i , i + L − 1 ] [i,i+L-1] [i,i+L1] [ j , j + L − 1 ] [j,j+L-1] [j,j+L1]

此时以 i i i开始, [ j + k − 1 , j + L − 1 ] [j+k-1,j+L-1] [j+k1,j+L1]为结束的字符串满足题面的要求。
但是可以在同一个i,不同个j会有重复,所以对于同一个i,将上面的 [ j + k − 1 , j + L − 1 ] [j+k-1,j+L-1] [j+k1,j+L1]作为线段,塞到vector里面sort后去重。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-04-02-19.23.43
 */
#include
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<x<<" ";test(args...);}
const LL mod=1e9+9;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

char x[2009];
LL has[2009];
LL bas[2009];
LL getHash(int l,int r){
    return (has[r]-has[l-1]*bas[r-l+1]%mod+mod)%mod;
}

int main(){
    scanf("%s",x+1);
    int len=strlen(x+1);
    bas[0]=1;
    has[0]=0;
    rep(i,1,len){
        bas[i]=bas[i-1]*103%mod;
        has[i]=(has[i-1]*103+(x[i]-'a'))%mod;
    }
    int k;cin>>k;
    int sum=0;
    rep(i,1,len){
        vector<pill>V;
        rep(j,i+k+1,len){
            if(j+k-1>len)break;
            if(getHash(i,i+k-1)!=getHash(j,j+k-1))continue;
            int l=k,r=min(len-j+1,j-1-i),ans=k;
            while(l<=r){
                int mid=l+r>>1;
                if(getHash(i,i+mid-1)==getHash(j,j+mid-1))ans=mid,l=mid+1;
                else r=mid-1;
            }
            V.push_back({j+k-1,j+ans-1});
        }
        if(V.empty())continue;
        sort(V.begin(),V.end());
        int l=V[0].fi,r=V[0].se;

        for(auto P:V){
            if(P.fi>r+1){
                sum+=r-l+1;
                l=P.fi,r=P.se;
            }
            else{
                r=max(r,P.se);
            }
        }
        sum+=r-l+1;
    }
    printf("%d\n",sum);
    return 0;
}

/*_________________________________________________________end*/

你可能感兴趣的:(字符串,二分)