poj 2774 二分+hash

poj 2774
求两个字符串的最长公共子串,可以二分长度,把A串中长度为mid的子串的hash值存入hash table里(set map也可),在B串中枚举子串判断是否存在hash table里。hash的常数较大,比后缀数组、后缀自动机的解法较慢,模板长度也不小(我的代码用双hash,第一个hash检索table中的下标,第二个hash判断冲突时是否相等,hash_table中的tim作为计数器,用来初始多组数据,避免多次memset超时)。

#include 
#include 
#include 
#include 
#include 
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>1;
            check(mid) ? le=mid : ri=mid;
        }
        printf("%d\n",le);
    }
    return 0;
}

你可能感兴趣的:(poj 2774 二分+hash)