題目大意就是給出乙個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的字串,字串中只包含大小寫...