poj 2774 二分+hash

poj 2774
求兩個(gè)字符串的最長公共子串,可以二分長度,把A串中長度為mid的子串的hash值存入hash table里(set map也可),在B串中枚舉子串判斷是否存在hash table里。hash的常數(shù)較大,比后綴數(shù)組、后綴自動(dòng)機(jī)的解法較慢,模板長度也不小(我的代碼用雙hash,第一個(gè)hash檢索table中的下標(biāo),第二個(gè)hash判斷沖突時(shí)是否相等,hash_table中的tim作為計(jì)數(shù)器,用來初始多組數(shù)據(jù),避免多次memset超時(shí))。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn=1e5+100;
const int ha1=443,ha2=317,mod=1000099;
struct Point
{
    int x,y;
    Point(int a=0,int b=0) { x=a,y=b; }
    friend Point operator + (const Point &a,const Point &b)
    {
        return Point((a.x+b.x) % mod,(a.y+b.y) % mod);
    }
    friend Point operator - (const Point &a,const Point &b)
    {
        return Point((a.x-b.x+mod) % mod,(a.y-b.y+mod) % mod);
    }
    friend Point operator * (const Point &a,const Point &b)
    {
        return Point((long long)a.x*b.x % mod, (long long)a.y*b.y % mod);
    }
    friend bool operator == (const Point &a,const Point &b)
    {
        return (a.x==b.x && a.y==b.y);
    }
};

struct hash_table
{
    int tim;
    int vis[mod],key2[mod];

    hash_table()
    {
        tim=0;
        memset(vis,0,sizeof(vis));
        memset(key2,0,sizeof(key2));
    }
    void init()
    {
        tim++;
    }
    int get_pos(const Point &a)
    {
        int pos=a.x,v=a.y;
        for (; vis[pos]==tim && key2[pos]!=v; pos+=11,pos%=mod);
        return pos;
    }
    void insert(const Point &a)
    {
        int pos=get_pos(a);
        vis[pos]=tim;
        key2[pos]=a.y;
    }
    bool find(const Point &a)
    {
        int pos=get_pos(a);
        return (vis[pos]==tim);
    }
};

Point po[maxn],sum1[maxn],sum2[maxn];
hash_table HT;
char A[maxn],B[maxn];
int N,M;

void Prepare_hash()
{
    po[0]=Point(1,1);
    po[1]=Point(ha1,ha2);
    for (int i=2; i<maxn; i++)
        po[i]=po[i-1]*po[1];
}

void get_hash(char *s,Point *sum,int len)
{
    sum[0]=Point(0,0);
    for (int i=1; i<=len; i++)
        sum[i]=sum[i-1]+po[i]*Point(s[i],s[i]);
}

bool check(int len)
{
    int U=max(N,M);
    HT.init();
    for (int i=1; i<=N-len+1; i++)
    {
        Point p=sum1[i+len-1]-sum1[i-1];
        p=p*po[U-i];
        HT.insert(p);
    }
    for (int i=1; i<=M-len+1; i++)
    {
        Point p=sum2[i+len-1]-sum2[i-1];
        p=p*po[U-i];
        if (HT.find(p)) return true;
    }
    return false;
}

int main()
{
    Prepare_hash();
    for (; scanf("%s%s",A+1,B+1)!=EOF; )
    {
        N=strlen(A+1);
        M=strlen(B+1);
        get_hash(A,sum1,N);
        get_hash(B,sum2,M);
        int le=0,ri=min(N,M)+1;
        while(le+1<ri)
        {
            int mid=(le+ri)>>1;
            check(mid) ? le=mid : ri=mid;
        }
        printf("%d\n",le);
    }
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx?那么一定聽過它的“同行”Apache吧!Ngi...
    JokerW閱讀 33,040評論 24 1,002
  • 教你如何迅速秒殺掉:99%的海量數(shù)據(jù)處理面試題 本文經(jīng)過大量細(xì)致的優(yōu)化后,收錄于我的新書《編程之法》第六章中,新書...
    Helen_Cat閱讀 7,591評論 1 39
  • 作者:July、wuliming、pkuoliver 說明:本文分為三部分內(nèi)容,第一部分為一道百度面試題Top K...
    cyj_ya閱讀 917評論 0 0
  • 【視也導(dǎo)讀】從給整車導(dǎo)流到做城際整車垂直創(chuàng)業(yè),福佑卡車單丹丹坦言,在這樣的交易場景下,價(jià)格是一方面,貨物安全的交付...
    視也閱讀 259評論 0 1
  • 從明天起!做一個(gè)積極樂觀的人!早起,運(yùn)動(dòng),打掃房間!不為整潔,只為忘卻思念! 從明天起,做一個(gè)有理想的人...
    綠蘿悠悠閱讀 151評論 0 0

友情鏈接更多精彩內(nèi)容