BZOJ2351Matrix (矩陣) 二維雜湊

2021-09-26 00:00:43 字數 1821 閱讀 1856

給定乙個m行n列的01矩陣(只包含數字0或1的矩陣),再執行q次詢問,每次詢問給出乙個a行b列的01矩陣,求該矩陣是否在原矩陣**現過。

輸入格式

第一行四個整數m,n,a,b。

接下來乙個m行n列的01矩陣,數字之間沒有空格。

接下來乙個整數q。

接下來q個a行b列的01矩陣,數字之間沒有空格。

輸出格式

對於每個詢問,輸出1表示出現過,0表示沒有出現過。

資料範圍

a≤100a≤100,m,n,b≤1000m,n,b≤1000,q≤1000q≤1000

輸入樣例:

3 3 2 2

111000

1113

1100

1111

0011

輸出樣例:

1

01

這是二維的字串的hash,一維的字串hash具體原理:

我們知道單行的任意子串的hash如何求了,如何擴充套件的二維的,怎麼求乙個大矩陣任意a*b的子矩陣的hash呢,其實也是差不多的。如圖,

0,1,2,3,4,5我們表示對其的p進製上的第幾位。

我們假設已經求出s為矩陣a*b的hash,那我們如何計算藍色矩陣的hash,先給出公式:

s*p^b+h[a+1][l~r]-h[1][l~r]*p^(a*b)

h[a+1][l~r]儲存a+1行字串區間[l,r]子串的雜湊值,[l,r]相當於[1,b]

解釋: s*p^b相當於把其往高位移動了一位(每乙個位置相當於提高了兩位),然後加上個位h[a+1][l~r],然後減去第一行的

h[1][l~r]*p^(a*b)。

//核心思想:將字串看成p進製數,p的經驗值是131或13331,取這兩個值的衝突概率低

//小技巧:取模的數用2^64,這樣直接用unsigned long long儲存,溢位的結果就是取模的結果

//如果超時改為unsigned int

#includeusing namespace std;

typedef unsigned long long ull;

const int n=1e3+5;

ull hashv[n][n], power[n*n]; // hashv[k]儲存字串前k個字母的雜湊值, power[k]儲存 p^k mod 2^64

char str[n][n],str1[n];

int n,m,a,b;

int p;

// 初始化

void calhash()

}power[0] = 1;

for(int i=1; i<=n*m; i++)

}// 計算子串 str[l ~ r] 的雜湊值

ull get(ull f,int l, int r)

int main()

calhash();

//將大小為a*b的矩陣hash儲存到hash中

unordered_sethash;

for(int i=b; i<=m; i++)

}int q;

scanf("%d",&q);

while(q--)

}if(hash.count(s))

printf("1\n");

else

printf("0\n");

}return 0;

}

bzoj2351 Matrix(二維雜湊)

description 給定乙個m行n列的01矩陣,以及q個a行b列的01矩陣,你需要求出這q個矩陣哪些在原矩陣 現過。所謂01矩陣,就是矩陣中所有元素不是0就是1。input 輸入檔案的第一行為m n a b,參見題目描述。接下來m行,每行n個字元,非0即1,描述原矩陣。接下來一行為你要處理的詢問...

Unity3D開發之Matrix4x4矩陣變換

在unity開發中時常會用到matrix4x4矩陣來變換場景中物件的位置 旋轉和縮放。但是很多人都不太理解這兒matrix4x4變換矩陣。通過dx中的變換矩陣我來講一講在unity中這個變換矩陣是怎麼變換的。在三維圖形程式中,我們可以用幾何變換來達到以下目的 你可以使用乙個4 4的矩陣將任何點變換到...

bzoj1084 SCOI2005 最大子矩陣

description 這裡有乙個n m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意 選出的k個子矩陣 不能相互重疊。input 第一行為n,m,k 1 n 100,1 m 2,1 k 10 接下來n行描述矩陣每行中的每個元素的分值 每個元素的 分值的絕對值不超過32767 ...