【二分答案】【哈希表】【字符串哈希】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 2007
typedef 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;
}
时间: 2024-11-05 18:49:46

【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串的相关文章

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

我们二分/分块枚举答案x,暴力把除了最短的字符串以外的其他字符串的x长度子串哈希搞出来,分别扔到set里. 然后暴力枚举最短的字符串的x长度字串,查看是否在全部的set里出现过. #include<cstdio> #include<set> #include<cstring> #include<cmath> using namespace std; typedef unsigned long long ull; set<ull>T[6]; con

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串

Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10800   Accepted: 2967 Description You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial traits such as height, colour, wrinkles, e

哈希表与哈希函数 C实现

<pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"> <strong>散列表</strong>(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通

哈希表和哈希函数

一.哈希表 通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f  以及处理冲突的方法,使得每个关键字和结构中一个唯一的存储位置相对应.这样对于关键字 K  根据对应关系 f  ,就可以找到存储在 f(K) .称这种对应关系f 为 哈希函数,按照这种方法建立的表称为哈希表. 1.1 原理: 通过记录的存储位置和它的关键字之间建立一个确定的对应关系 f ,使得每个关键字和结构中一个唯一的存储位置相对应.这样对于关键字 K  根据对应关系 f  ,就可以找到存储在 f(K) .称这种对应关系

浅谈算法和数据结构: 十一 哈希表

在前面的系列文章中,依次介绍了基于无序列表的顺序查找,基于有序数组的二分查找,平衡查找树,以及红黑树,下图是他们在平均以及最差情况下的时间复杂度: 可以看到在时间复杂度上,红黑树在平均情况下插入,查找以及删除上都达到了lgN的时间复杂度. 那么有没有查找效率更高的数据结构呢,答案就是本文接下来要介绍了散列表,也叫哈希表(Hash Table) 什么是哈希表 哈希表就是一种以 键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值. 哈希的思路很简单

从头到尾彻底解析哈希表算法

说明:本文分为三部分内容,第一部分为一道百度面试题Top K算法的详解:第二部分为关于Hash表算法的详细阐述:第三部分为打造一个最快的Hash表算法. 第一部分:Top K 算法详解 问题描述 百度面试题: 搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节. 假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个.一个查询串的重复度越高,说明查询它的用户越多,也就是越热门.),请你统计最热门的10个查

哈希表入门讲解

散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存存储位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录的数组称做散列表. 一个通俗的例子是,为了查找电话簿中某人的号码,可以创建一个按照人名首字母顺序排列的表(即建立人名{\displaystyle x}到首字母{\displaystyle F(x)}的一个函数关系),在首字母为W的表中查找"王"姓的电话号

散列表(哈希表)

1.按先后顺序存储在A[i]中,查找需要O(n),如果用二分查找,需要O(logn) 2.定义一个一维数组A[1..1353],使得A[key]=key,这样,查找只需O(1)就可以了,但空间开销比较大 思考:有什么办法使得查找时间快,占用空间小 哈希表基本原理 哈希表的基本原理是使用一个下标范围比较大的数组A来存储元素,设计一个函数h,对于要存储的线性表的每个元素node,取一个关键字key,算出一个函数值h(key),把h(key)作为数组下标,用A[h(key)]这个数组单元来存储node