POJ 2774——Long Long Message(二分+hash)

题意:

给出两个最长长为1e5的字符串,求他们的最长公共子串长度。

 思路:

分别将两个字符串预处理出hash值,二分【1-min(lens,lent)】的长度,check函数中每次将长度为mid的hash值记录并检查是否符合条件,是则下边界右移,否则上边界左移。复杂度O(nlogn)

 代码:

#include<stdio.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N =100000+5;

char s[N],t[N];
int lens,lent;
ull base=233;
ull p[N],hs[N],ht[N];
ull geths(int l,int r)
{
    return hs[r]-p[r-l+1]*hs[l-1];
}
ull getht(int l,int r)
{
    return ht[r]-p[r-l+1]*ht[l-1];
}

int check(int len)
{
    vector<ull>mp;
    for(int i=1; i<=lens-len+1; i++)
    {
        ull tmp=geths(i,i+len-1);
        mp.push_back(tmp);
    }
    sort(mp.begin(),mp.end());
    for(int i=1; i<=lent-len+1; i++)
    {
        ull tmp=getht(i,i+len-1);
        if(binary_search(mp.begin(),mp.end(),tmp)) return 1;
    }
    return 0;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    p[0]=1;
    for(int i=1; i<N; i++) p[i]=p[i-1]*base;
    while(~scanf("%s%s",s+1,t+1))
    {
        lens=strlen(s+1);
        lent=strlen(t+1);
        for(int i=1; i<=lens; i++)
        {
            hs[i]=hs[i-1]*base+s[i]-'a';
        }
        for(int i=1; i<=lent; i++)
        {
            ht[i]=ht[i-1]*base+t[i]-'a';
        }
        int l=1,r=min(lens,lent),mid;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(check(mid)) l=mid+1;
            else        r=mid-1;

        }
        printf("%d\n",r);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值