一看题冒出各种奇奇怪怪不可做的想法
其实做法也很简单
把每行作为模式串插入AC自动机
再拿小矩阵每行去匹配
在匹配成功之后需要搞点事情
匹配成功后给对应的左上角的计数器加一
最后统计一遍即可
代码里有一些特别奇怪的东西,比如拿邻接表存相同的行什么的(要不会MLE)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;
const int MAXN = 1002, MAXX = 102, MAXNnode = 1000002;
struct Node{
int tag, fail, nxt[26];
inline void init(){tag = fail = 0; memset(nxt, 0, sizeof(nxt));}
}t[MAXNnode];
int T, n, m, n2, m2, ptr, Root;
int cnt[MAXN][MAXN], head[MAXX];
char txt[MAXN][MAXN], str[MAXX][MAXX];
queue<int> q;
inline void Insert(int No) {
int cur = Root;
for(int i = 1; i <= m2; ++i) {
register int x = str[No][i] - 'a';
if(!t[cur].nxt[x]) {
t[cur].nxt[x] = ++ptr;
t[ptr].init();
}
cur = t[cur].nxt[x];
}
if(t[cur].tag) head[No] = t[cur].tag;
t[cur].tag = No;
return;
}
inline void getfail() {
t[Root].fail = 0;
for(int i = 0; i < 26; ++i)
if(t[Root].nxt[i]) {
t[t[Root].nxt[i]].fail = Root;
q.push(t[Root].nxt[i]);
} else t[Root].nxt[i] = Root;
while(!q.empty()) {
int cur = q.front(); q.pop();
for(int i = 0; i < 26; ++i) {
register int son = t[cur].nxt[i];
if(!son) {
t[cur].nxt[i] = t[t[cur].fail].nxt[i];
continue;
}
t[son].fail = t[t[cur].fail].nxt[i];
if(t[t[son].fail].tag) t[son].tag = t[t[son].fail].tag;
q.push(son);
}
}
return;
}
inline void update(int x, int y, int z) {
if(x >= z) ++cnt[x - z + 1][y - m2 + 1];
while(head[z]) {
z = head[z];
if(x >= z) ++cnt[x - z + 1][y - m2 + 1];
}
return;
}
inline void acfind() {
int cur = Root;
for(int i = 1; i <= n; ++i) {
cur = Root;
for(int j = 1; j <= m; ++j) {
cur = t[cur].nxt[txt[i][j] - 'a'];
if(t[cur].tag)
update(i, j, t[cur].tag);
}
}
return;
}
inline void resetall() {
ptr = 0;
memset(t + Root, 0, sizeof(Node));
memset(head, 0, sizeof(head));
for(int i = 0; i <= n; ++i)
for(int j = 0; j <= m; ++j)
cnt[i][j] = 0;
return;
}
inline int rd() {
register int x = 0;
register char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)) {
x = x * 10 + (c ^ 48);
c = getchar();
}
return x;
}
int main() {
T = rd();
while(T--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%s", txt[i] + 1);
scanf("%d%d", &n2, &m2);
for(int i = 1; i <= n2; ++i) {
scanf("%s", str[i] + 1);
Insert(i);
}
getfail();
acfind();
int ans = 0;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
if(cnt[i][j] >= n2) ++ans;
}
}
printf("%d
", ans);
resetall();
}
return 0;
}