首页 > 代码库 > 【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串

【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串

二分答案,然后搞出hash值扔到哈希表里。期望复杂度O(n*log(n))。

#include<cstdio>#include<cstring>#include<vector>using namespace std;typedef unsigned long long ull;const ull seed=29;#define MOD 2007typedef vector<ull>::iterator VER;vector<ull>List[6][2007];ull seeds[2001],ord[301];int n,ls[6],minv=2147483647,mini;char s[6][2001];ull BKDRhash(const char str[],const int &L,const int &R){    ull res=0;    for(int i=L;i<R;++i)      res=res*seed+ord[str[i]];    return res;}void init(){    for(int i=‘a‘,j=1;i<=‘z‘;++i,++j)      ord[i]=(ull)j;    seeds[0]=1;    for(int i=1;i<=minv;++i)      seeds[i]=seeds[i-1]*seed;}bool Find(const int &o,const ull &x){	int y=(int)(x%MOD);	for(VER it=List[o][y].begin();it!=List[o][y].end();++it)	  if(*it==x)	    return 1;	return 0;}bool Find_In_All(const ull &x){    for(int i=1;i<=n;++i)      if(i!=mini&&(!Find(i,x)))        return 0;    return 1;}bool check(const int &x){    for(int i=1;i<=n;++i) if(i!=mini)      {        ull hs=BKDRhash(s[i],0,x);        List[i][hs%MOD].push_back(hs);        for(int j=x;j<ls[i];++j)          {            hs=hs*seed+ord[s[i][j]];            hs-=seeds[x]*ord[s[i][j-x]];            List[i][hs%MOD].push_back(hs);          }      }    ull hs=BKDRhash(s[mini],0,x);    if(Find_In_All(hs)) return 1;    for(int i=x;i<minv;++i)      {        hs=hs*seed+ord[s[mini][i]];        hs-=seeds[x]*ord[s[mini][i-x]];        if(Find_In_All(hs)) return 1;      }    return 0;}int main(){	scanf("%d",&n);    for(int i=1;i<=n;++i)      {        scanf("%s",s[i]);        ls[i]=strlen(s[i]);        if(ls[i]<minv)          {            minv=ls[i];            mini=i;          }      }    init();    int l=0,r=minv+1;    while(l<r)	  {          int mid=l+r>>1;          if(check(mid)) l=mid+1;          else r=mid;      }	printf("%d\n",l-1);	return 0;}

【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串