POJ3690 字串雜湊 星座

2021-08-25 02:19:25 字數 1505 閱讀 5080

題目大意就是給出乙個n * m的矩陣,矩陣中只有一些*或者0,n <= 1000, m <= 1000

然後有t (t <= 100)個詢問,每次詢問給出乙個p * q的矩陣,p,q是提前固定的數值。

問這些詢問中是大矩陣的子矩陣的有幾個

如果暴力查詢,時間複雜度為t*n*m*p*q。

用雜湊優化一下,我們每次詢問的時候把詢問的矩陣用雜湊處理成乙個數字,然後把大矩陣的每乙個p*q的子矩陣都處理成乙個數字,這樣做的時間複雜度為n*m(我自己估算的值)。

我們已經知道了如何用雜湊處理乙個字串,就是把字串看成乙個b進製的數字,每乙個數字上的值由字串本身決定。乙個字串的雜湊值已經求出來之後,它後移一位的字串的雜湊值也很好求,只要乘乙個b,再把前面的那一位減掉,並把後面那一位加上就可以了。(這是針對固定長度的字串)

然後如何求乙個矩陣字串的雜湊值呢?很簡單,把每一行的雜湊值求出來,再把求出來的雜湊值看成乙個字串,取另外乙個值b2來計算這個新字串的雜湊值即可。

unsigned long long 無符號位整型,溢位時會自動取模。另外,在計算字串雜湊的時候每一位上的數值不要取0,因為如果取零的話會不好區分字串的長度。

multiset,包含在標頭檔案set當中,與set的區別是可以包含重複元素。

#include #include using namespace std;

typedef unsigned long long ull;

const ull b1=9997, b2=1000007;

char s[1005], h[100];

ull a[1005][1005], b[1005][1005], tmp[1005][1005], ha[1005][1005];

int n, m, t, p, q;

multisetunseen;

void cal(ull a[1005][1005], int n, int m) //計算矩陣a的所有p*q的子矩陣的雜湊值

} ull t2=1;

for (int i = 0; i < p; i++) t2 *= b2;

for (int j = 0; j+q <= m; j++)

} }int main()

} unseen.clear();

for (int i = 0; i < t; i++)

}cal(b, p, q);

unseen.insert(ha[0][0]); //把所有的詢問的矩陣的雜湊值存在multiset中

} cal(a, n, m); //計算大矩陣中的所有p*q的子矩陣的雜湊值

for (int i = 0; i+p <= n; i++) //列舉大矩陣中所有的p*q的子矩陣的雜湊值

}int ans=t-unseen.size();

printf("case %d: %d\n",u, ans);

} return 0;

}

16 字串雜湊 雜湊表

這個方法叫做字串字首雜湊法 先求出來每個字首的雜湊值 問題1 如何來定義某乙個字首的雜湊值 把這個字串看成是乙個p進製的數 每一位上的字母的ascii碼,就是這一位上的數 最後mod上乙個很小的數,就對映到0 q 1 這樣就可以把乙個字串轉換為乙個數字 注意事項1 一般情況下,不能把某個字母對映成0...

POJ 2774 字串雜湊 二分

題意 給出s,t兩個字串,求最長公共子串的長度 思路 首先二分答案x,預處理出s中長度為x的子串雜湊值並排序,在t中列舉起點,二分查詢t i.i x 的雜湊值 二分查詢直接用binary search 函式 複雜度其實是nlog方 1 include2 include3 include4 inclu...

Acwing 841 字串雜湊 字首雜湊

給定乙個長度為n的字串,再給定m個詢問,每個詢問包含四個整數l1,r1,l2,r2,請你判斷 l1,r1 和 l2,r2 這兩個區間所包含的字串子串是否完全相同。字串中只包含大小寫英文本母和數字。輸入格式 第一行包含整數n和m,表示字串長度和詢問次數。第二行包含乙個長度為n的字串,字串中只包含大小寫...