题目链接:https://vjudge.net/problem/Gym-100783J http://codeforces.com/gym/100783
题意:给你一个 a * b 大小的二维字符串,问其在一个 n * m 大小的二维字符串中出现的次数。
思路:二维字符串hash,先一行一行的hash,把每行的hash值再按列进行hash,两次使用的 base 不同。
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; typedef unsigned long long ull; const int N = 2010; const ull base1 = 131; const ull base2 = 233; int n, m, p, q; char s1[N][N]; char s2[N][N]; ull r[N][N]; ull c[N][N]; ull hash1; int main() { scanf("%d %d %d %d", &n, &m, &p, &q); for(int i = 0; i < n; i++) { getchar(); ull sum = 0; for(int j = 0; j < m; j++) { scanf("%c", &s1[i][j]); sum = sum * base1 + s1[i][j]; } hash1 = hash1 * base2 + sum; } for(int i = 0; i < p; i++) { getchar(); for(int j = 0; j < q; j++) scanf("%c", &s2[i][j]); } ull now = 1; for(int i = 0; i < m; i++) now *= base1; for(int i = 0; i < p; i++) { ull sum = 0; for(int j = 0; j < m; j++) { sum = sum * base1 + s2[i][j]; } r[i][m - 1] = sum; for(int j = m; j < q; j++) { r[i][j] = r[i][j - 1] * base1 + s2[i][j] - s2[i][j - m] * now; } } now = 1; int ans = 0; for(int i = 0; i < n; i++) now *= base2; for(int i = m - 1; i < q; i++) { ull sum = 0; for(int j = 0; j < n; j++) { sum = sum * base2 + r[j][i]; } c[n - 1][i] = sum; if(c[n - 1][i] == hash1) { // cout << n - 1 << " " << i << endl; ans++; } for(int j = n; j < p; j++) { c[j][i] = c[j - 1][i] * base2 + r[j][i] - r[j - n][i] * now; if(c[j][i] == hash1) { // cout << j << " " << i << endl; ans++; } } } printf("%d\n", ans); return 0; }
原文:https://www.cnblogs.com/lsl127/p/12870403.html