首页 > 其他分享 >BZOJ 3097(Hash Killer I-哈希%u64的不可行)

BZOJ 3097(Hash Killer I-哈希%u64的不可行)

时间:2022-10-25 11:04:38浏览次数:72  
标签:Hash val int Killer u64 li base hash VFleaKing


3097: Hash Killer I


Time Limit: 5 Sec   Memory Limit: 128 MBSec   Special Judge

Submit: 76  

Solved: 34

[​​Submit​​][​​Status​​][​​Discuss​​]


Description


这天天气不错,hzhwcmhf神犇给VFleaKing出了一道题:
给你一个长度为N的字符串S,求有多少个不同的长度为L的子串。
子串的定义是S[l]、S[l + 1]、... S[r]这样连续的一段。
两个字符串被认为是不同的当且仅当某个位置上的字符不同。

VFleaKing一看觉得这不是Hash的裸题么!于是果断写了哈希 + 排序。
而hzhwcmhf神犇心里自然知道,这题就是后缀数组的height中 < L的个数 + 1,就是后缀自动机上代表的长度区间包含L的结点个数,就是后缀树深度为L的结点的数量。
但是hzhwcmhf神犇看了看VFleaKing的做法表示非常汗。于是想卡掉他。

VFleaKing使用的是字典序哈希,其代码大致如下:
u64 val = 0;
for (int i = 0; i < l; i++)
 val = val * base + s[i] - 'a';
u64是无符号int64,范围是[0, 2^64)。VFleaKing让val自然溢出。
base是一个常量,VFleaKing会根据心情决定其值。
VFleaKing还求出来了base ^ l,即base的l次方,这样就能方便地求出所有长度为L的子串的哈希值。
然后VFleaKing给哈希值排序,去重,求出有多少个不同的哈希值,把这个数作为结果。
其算法的C++代码如下:

typedef unsigned long long u64;
const int MaxN = 100000;
inline int hash_handle(const char *s, const int &n, const int &l, const int &base)
{
u64 hash_pow_l = 1;
for (int i = 1; i <= l; i++)
hash_pow_l *= base; int li_n = 0;
static u64 li[MaxN]; u64 val = 0;
for (int i = 0; i < l; i++)
val = val * base + s[i] - 'a';
li[li_n++] = val;
for (int i = l; i < n; i++)
{
val = val * base + s[i] - 'a';
val -= (s[i - l] - 'a') * hash_pow_l;
li[li_n++] = val;
} sort(li, li + li_n);
li_n = unique(li, li + li_n) - li;
return li_n;
}

hzhwcmhf当然知道怎么卡啦!但是他想考考你。


Input


没有输入。


Output


你需要输出一组数据使得VFleaKing的代码WA掉。我们会使用Special Judge检查你的结果的正确性。
输出文件共两行。
第一行两个用空格隔开的数n、l。
第二行是一个长度为n的字符串。只能包含'a'~'z'。
需要保证1 <= n <= 10^5, 1 <= l <= n,
不符合以上格式会WA。
不要有多余字符,很可能导致你WA。


Sample Input


没有


Sample Output


8 4
buaabuaa
(当然这个输出是会WA的)


HINT


orz 波兰人 & fotile96 & sillycross



这题要一定的数论知识(其实不要……)

如果s[1]=1 s[i]=s[i-1]+s[i-1].flip(1...size)

则有

strlen(s[i])=2^(i-1)

若设f[i]=hash(s[i])-(hash(!s[i]))=2^k * t (t是奇数)

则易证(把hash值有base带,慢慢算……)

f[i]=f[i-1]*(base^[2^(i-2)]-1)

∵2^i-1=(2^(i-1)-1)*(2^(i-1)+1),

所以k很大。  

如果base是偶数,那么只要最高位不同,其它都相同让其溢出就行。


#include<cstdio>
#include<iostream>
#include<functional>
#include<bitset>
#include<string>
using namespace std;
#define MAXN (100000+10)
int n,l;
bitset<MAXN> s;
int main()
{
n=MAXN-10;
int bin=1;
s[1]=1;
for (int i=2;i<=13;i++,bin<<=1)
{
for(int j=bin+1;j<=bin*2;j++)
s[j]=s[j-bin]^1;
}
cout<<n<<' '<<bin/2<<endl;
for (int i=1;i<=bin;i++)
{
if (s[i]) cout<<'a';
else cout<<'b';
}
cout<<'b';
for (int i=bin+2;i<=n;i++) cout<<'a';

cout<<endl;
return 0;
}



标签:Hash,val,int,Killer,u64,li,base,hash,VFleaKing
From: https://blog.51cto.com/u_15724837/5794149

相关文章

  • 6.HashMap源码解析
    1.数据结构如上图所示,HashMap底层的数据结构主要是数组+链表+红黑树。其中当链表的长度大于等于8时,链表会转化成红黑树,当红黑树的大小小于等于6时,红黑树会转化成链表。......
  • 2.3 RedisAPI之hash
    1.简介字符串键值结构(keyfieldvalue)2.命令设置key对应的field的valuehsetkeyfieldvalue时间复杂度为O(1)获取key对应的field的valuehgetkeyfieldvalue时间复杂度......
  • currenthashmap(currenthashmap和hashmap的区别)
    concurrenthashmap的读是否要加锁,为什么有并发访问的时候用ConcurrentHashMap,效率比用锁的HashMap好功能上可以,但是毕竟ConcurrentHashMap这种数据结构要复杂些,如果能保证只......
  • BZOJ 4373(算术天才⑨与等差数列-线段树+hash)
    Description算术天才⑨非常喜欢和等差数列玩耍。有一天,他给了你一个长度为n的序列,其中第i个数为a[i]。他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序......
  • HashSet集合 Array sort方法 学习 剑指offer 练习1
    HashSet集合是基于HashMap来实现的,不允许有重复的元素        允许有NULL值 无序,不会记录插入的顺序HashSet实例化对象  HashSet<Strin......
  • CF 869E(The Untended Antiquity-Hash值维护连通性)
    一个地图,然后三种操作1.一个矩阵四周加上障碍(不与任何障碍相交)2.一个矩阵四周的障碍消除3.问你两个点之间是否纯在一条路径不经过障碍矩阵大小2500^2,操作10w树状......
  • hash 表
    Hash表1E5个数,数据范围在1E-9到1E9,需要查找某个数,Hash表用接近O(1)的时间办到,进行映射,取模,映射到某个数,模谁呢,这个数一般是比较大的质数,这样矛盾的概率就比较小。拉链法......
  • java基础HashSet 集合TreeSet集合
           ......
  • 今天聊下Java中的HashMap---Java中用的就很多的集合框架
    先说下HashMap的定义HashMap是一个散列表,存储的内容是键值对(key-value)映射。HashMap实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键......
  • HashMap 源码分析(五)
    ......