計蒜客 UCloud 的安全秘鑰(困難)(哈希)


UCloud 的安全秘鑰(困難)

 

  •  9.53%
  •  1200ms
  •  262144K

每個 UCloud 用戶會構造一個由數字序列組成的秘鑰,用於對服務器進行各種操作。作為一家安全可信的雲計算平台,秘鑰的安全性至關重要。因此,UCloud 每年會對用戶的秘鑰進行安全性評估,具體的評估方法如下:

首先,定義兩個由數字序列組成的秘鑰 aa 和 bb 近似匹配(\approx≈) 的關系。aa 和 bb 近似匹配當且僅當同時滿足以下兩個條件:

  • |a|=|b|a=b∣,即 aa 串和 bb 串長度相等。
  • 對於每種數字 cc,cc 在 aa 中出現的次數等於 cc 在 bb 中出現的次數。

此時,我們就稱 aa 和 bb 近似匹配,即 a \approx bab。例如,(1,3,1,1,2)\approx(2,1,3,1,1)(1,3,1,1,2)(2,1,3,1,1)。

UCloud 每年會收集若干不安全秘鑰,這些秘鑰組成了不安全秘鑰集合 TT。對於一個秘鑰 ss 和集合 TT 中的秘鑰 tt來說,它們的相似值定義為:ss 的所有連續子串中與 tt 近似匹配的個數。相似值越高,說明秘鑰 ss 越不安全。對於不安全秘鑰集合 TT 中的每個秘鑰 tt,你需要輸出它和秘鑰 ss 的相似值,用來對用戶秘鑰的安全性進行分析。

輸入格式

第一行包含一個正整數 nn,表示 ss 串的長度。

第二行包含 nn 個正整數 s_1,s_2,...,s_n(1\leq s_i\leq n)s1​​,s2​​,...,sn​​(1si​​n),表示 ss 串。

接下來一行包含一個正整數 mm,表示詢問的個數。

接下來 mm 個部分:

每個部分第一行包含一個正整數 k(1\leq k\leq n)k(1kn),表示每個 tt 串的長度。

每個部分第二行包含 kk 個正整數 t_1,t_2,...,t_k(1\leq t_i\leq n)t1​​,t2​​,...,tk​​(1ti​​n),表示 TT 中的一個串 tt。

輸入數據保證 TT 中所有串長度之和不超過 200000200000。

對於簡單版本:1\leq n,m\leq 1001n,m100;

對於中等版本:1\leq n\leq 50000,1\leq m\leq 5001n50000,1m500;

對於困難版本:1 \le n \le 50000, 1 \le m \le 1000001n50000,1m100000。

輸出格式

輸出 mm 行,每行一個整數,即與 TT 中每個串 tt 近似匹配的 ss 的子串數量。

樣例解釋

對於第一個詢問,(3,2,1,3)\approx(2,3,1,3)(3,2,1,3)(2,3,1,3),(3,2,1,3)\approx(3,1,3,2)(3,2,1,3)(3,1,3,2);

對於第二個詢問,(1,3)\approx(3,1)(1,3)(3,1),(1,3)\approx(1,3)(1,3)(1,3);

對於第三個詢問,(3,2)\approx(2,3)(3,2)(2,3),(3,2)\approx(3,2)(3,2)(3,2)。

樣例輸入

5
2 3 1 3 2
3
4
3 2 1 3
2
1 3
2
3 2

樣例輸出

2
2
2
【分析】給你一個原始數組,數組里每個數都<=n;然后K次詢問,每次詢問給出一個新的數組,問你原始數組中有多少連續子串是給定數組的
一種重新排列。
對於中等難度的,可以雙指針搞一下,但是對於困難的就不會了,看了題解才知道...對於詢問給定的數組的總長最大為2000000,而每次給
定的數組最長為50000.也就是說對於一個數組的長度m,不同的m的種數最多才650種。那么我們可以離線,將同種長度的存在一起。然后將
原始的數組的各種長度的m的哈希值算出來,然后排個序,對於此長度的詢問的數組就可以根據哈希值二分來統計答案了。那么現在的問題是
怎么哈希...看了題解才知道后還有這種哈希的姿勢,給每個數隨機一個16位的數,就是ull rand()*rand()...學習到新知識了。
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define met(a,b) memset(a,b,sizeof a)
using namespace std;
typedef
long long ll;
typedef unsigned
long long ull;
typedef pair
<int,int>pii;
const int N = 2e5+5;
const int mod = 1e9+7;
int n,m,k,u;
int a[N];
int b[N],ans[N];
ll has[N];
ull sum[N];
vector
<pair<ull,int> >vec[N];
vector
<int>c;
vector
<ull>q;
int main()
{
scanf(
"%d",&n);
for(int i=1;i<=n;i++)has[i]=(ull)rand()*rand();
for(int i=1; i<=n; i++){
scanf(
"%d",&a[i]);
sum[i]
=sum[i-1]+has[a[i]];
}
scanf(
"%d",&k);
for(int i=1;i<=k;i++){
scanf(
"%d",&m);
if(!b[m])c.pb(m),b[m]=1;
ull s
=0;
for(int i=1; i<=m; i++){
scanf(
"%d",&u);
s
+=has[u];
}
vec[m].pb(mp(s,i));
}
for(int x:c){
if(x>n){
for(pair<ull,int> p : vec[x]){
int id = p.second;
ans[id]
=0;
}
}
else {
ull s
=0;
q.clear();
for(int l=1,r=1;r<=n;r++){
s
+=has[a[r]];
if(r-l+1==x){
q.pb(s);
s
-=has[a[l++]];
}
}
sort(q.begin(),q.end());
for(pair<ull,int> p : vec[x]){
int id = p.second;
ull s
= p.first;
ans[id]
=upper_bound(q.begin(),q.end(),s)-lower_bound(q.begin(),q.end(),s);
}
}
}
for(int i=1;i<=k;i++){
printf(
"%d\n",ans[i]);
}
return 0;
}

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com