题目大意:给你一个矩阵T,问另一个矩阵P在这个矩阵T中出现过几次
可以用hash水,常数还小,双hash还卡不了
正解是把P每一行作为一个串,建一个AC自动机
用T的每一行去匹配,维护tot[i][j]表示T中左上角为i,j的T大小的矩阵,出现了T中的多少行
答案为tot[i][j] = x的i,j个数
各种卡常+反复提交,终于过了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #define min(a, b) ((a) < (b) ? (a) : (b)) 7 #define max(a, b) ((a) > (b) ? (a) : (b)) 8 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 9 inline void swap(int &a, int &b) 10 { 11 long long tmp = a;a = b;b = tmp; 12 } 13 inline void read(int &x) 14 { 15 x = 0;char ch = getchar(), c = ch; 16 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 17 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 18 if(c == ‘-‘) x = -x; 19 } 20 21 const int INF = 0x3f3f3f3f; 22 const int MAXNODE = 10000 + 1; 23 const int MAXLEN = 1000 + 1; 24 25 int t,n,m,x,y,ans,cnt, tag[MAXNODE], ch[27][MAXNODE], tot[MAXLEN][MAXLEN], fail[MAXNODE], last[MAXNODE]; 26 char T[MAXLEN][MAXLEN], P[MAXLEN][MAXLEN]; 27 std::vector<int> node[MAXNODE]; 28 29 int bq[MAXNODE], btot; 30 void insert(int x) 31 { 32 int now = 0; 33 for(int i = 1;P[x][i] != ‘\0‘;++ i) 34 { 35 int &tmp = ch[P[x][i] - ‘a‘ + 1][now]; 36 if(tmp) now = tmp; 37 else now = tmp = ++ cnt; 38 } 39 ++ tag[now], node[now].push_back(x); 40 bq[++ btot] = now; 41 } 42 43 int q[MAXNODE], he, ta; 44 45 void build() 46 { 47 he = ta = 0; 48 for(int i = 1;i <= 26;++ i) 49 { 50 int tmp = ch[i][0]; 51 if(tmp) q[ta ++] = tmp, fail[tmp] = last[tmp] = 0; 52 } 53 while(he < ta) 54 { 55 int now = q[he ++]; 56 for(register int i = 1;i <= 26;++ i) 57 { 58 int u = ch[i][now]; 59 if(!u) 60 { 61 ch[i][now] = ch[i][fail[now]]; 62 continue; 63 } 64 q[ta ++] = u; 65 int v = fail[now]; 66 while(v && !ch[i][v]) v = fail[v]; 67 fail[u] = ch[i][v]; 68 last[u] = tag[fail[u]] ? fail[u] : last[fail[u]]; 69 } 70 } 71 } 72 73 //在P中找T的第x行 74 void find(int u) 75 { 76 int j = 0; 77 for(int i = 1;i <= m;++ i) 78 { 79 j = ch[T[u][i] - ‘a‘ + 1][j]; 80 if(tag[j]) 81 { 82 for(int k = 0;k < node[j].size();++ k) 83 if(u - node[j][k] + 1 >= 1) ++ tot[u - node[j][k] + 1][i - y + 1]; 84 } 85 else if(last[j]) 86 { 87 for(int k = 0;k < node[last[j]].size();++ k) 88 if(u - node[last[j]][k] + 1 >= 1) ++ tot[u - node[last[j]][k] + 1][i - y + 1]; 89 } 90 } 91 } 92 93 int main() 94 { 95 read(t); 96 for(;t;--t) 97 { 98 for(int i = 1;i <= btot;++ i) node[bq[i]].clear(); 99 btot = 0; cnt = 0, memset(tot, 0, sizeof(tot)), memset(tag, 0, sizeof(tag)), ans = 0, memset(ch, 0, sizeof(ch)); 100 read(n), read(m); 101 for(int i = 1;i <= n;++ i) 102 scanf("%s", T[i] + 1); 103 read(x), read(y); 104 for(int i = 1;i <= x;++ i) 105 scanf("%s", P[i] + 1), insert(i); 106 if(n < x || m < y) 107 { 108 printf("0\n"); 109 continue; 110 } 111 build(); 112 for(int i = 1;i <= n;++ i) find(i); 113 for(int i = 1;i <= n - x + 1;++ i) 114 for(int j = 1;j <= m - y + 1;++ j) 115 if(tot[i][j] == x) ++ ans; 116 printf("%d\n", ans); 117 } 118 return 0; 119 }