题目
法一:字符串哈希,注意一下进制数取大一点;用getchar()+%c读入的时候会超时,用%s就不会,我在想%c是不是很慢。。
//#include<bits/stdc++.h>
#include<queue>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define mod (1000000007)
#define middle (l+r)>>1
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int inf_max = 0x3f3f3f3f;
const ll Linf = 9e18;
const int maxn = 1e3 + 10;
const int maxm = 5e4 + 10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
return f*res;
}
const ull base = 1000000007;
ull _hash[maxn][maxn],n,m,x,y,needhash,pre[maxn][maxn];
char ch[maxn][maxn],tar[maxn][maxn];
ull fpower(ull b,ull p) {
ull res = 1;
while(p) {
if(p & 1) res = res * b;
b = b * b;
p >>= 1;
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--) {
needhash = 0;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i) {
scanf("%s",ch[i] + 1);
for(int j = m;j >= 1; --j) {
_hash[i][j] = _hash[i][j+1] * base + (ull)ch[i][j];
}
}
scanf("%d%d",&x,&y);
for(int i = 1;i <= x; i++) {
scanf("%s",tar[i] + 1);
}
for(int i = x;i >= 1; --i)
for(int j = y;j >= 1;--j)
needhash = needhash * base + (ull)tar[i][j];
x--;y--;
int ans = 0;
//pre[i][j] 第i列从第n行到第j行代表的值
for(int j = 1;j + y <= m; ++j) { //第j 列为起点
for(int i = n;i >= 1; --i) { //第i行为起点
pre[j][i] = pre[j][i + 1] * fpower(base,y + 1) + _hash[i][j] - _hash[i][j + y + 1] * fpower(base,y + 1);
}
}
for(int i = 1;i + x <= n;++i) {
for(int j = 1;j + y <= m; ++j) {
ull tt = pre[j][i] - pre[j][i + x + 1] * fpower(base,(x+1) * (y+1));
if(tt == needhash) ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
法二:AC自动机,把第二个矩阵每一行作为一个模式串建立自动机,然后用第一个矩阵的每一行去匹配,如果匹配成功了某个串,就把这个串对应的左上角的行匹配次数++,然后遍历整个原矩阵,如果某个点的行匹配次数为x,那么答案就++;
//#include<bits/stdc++.h>
#include<queue>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define mod (1000000007)
#define middle (l+r)>>1
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int inf_max = 0x3f3f3f3f;
const ll Linf = 9e18;
const int maxn = 1e3 + 10;
const int maxm = 100 + 10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
int f=1,res=0;
char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
return f*res;
}
const int N = 30;
int n,m,x,y,match[maxn][maxn];
char s1[maxn][maxn];
struct AC {
int root,cnt,tree[maxm*maxm][N],fail[maxm*maxm*N],q[maxm*maxm*N],last[maxm*maxm*N];
vector<int>row[maxm*maxm*N];
int f,r;
int getnewnode() {
for(int i = 0;i < N; ++i) {
tree[cnt][i] = 0;
}
fail[cnt] = last[cnt] = 0;row[cnt].clear();
cnt++;
return cnt - 1;
}
void Initial() {
cnt = 0;
root = getnewnode();
f = r = 0;
}
void Insert(char *s,int r) {
int now = root,l = strlen(s + 1);
for(int i = 1;i <= l; ++i) {
int id = s[i] - 'a';
if(!tree[now][id]) tree[now][id] = getnewnode();
now = tree[now][id];
}
row[now].push_back(r);
}
void getfail() {
for(int i = 0;i < N; ++i) {
if(tree[0][i]) {
q[r++] = tree[0][i];
fail[tree[0][i]] = 0;
last[tree[0][i]] = (row[fail[tree[0][i]]].size() ? fail[tree[0][i]] : last[fail[tree[0][i]]]);
}
}
while(f != r) {
int u = q[f++];
for(int i = 0;i < N; ++i) {
if(tree[u][i]) {
fail[tree[u][i]] = tree[fail[u]][i];
q[r++] = tree[u][i];
}else tree[u][i] = tree[fail[u]][i];
last[tree[u][i]] = (row[fail[tree[u][i]]].size() ? fail[tree[u][i]] : last[fail[tree[u][i]]]);
}
}
}
void query(char *s,int r) {
int now = root,l = strlen(s + 1);
for(int i = 1;i <= l; ++i) {
now = tree[now][s[i] - 'a'];
int tmp = now,ind = 0;
while(tmp != root) {
for(int j = 0;j < row[tmp].size();++j) {
if(row[tmp][j]) {
if(r- row[now][j] + 1 > n) continue;
if(r- row[now][j] + 1 < 1) continue;
if(i- y + 1 > m) continue;
if(i- y + 1 < 1) continue;
match[r - row[now][j] + 1][i- y + 1]++;
}
}
tmp = last[tmp];
}
}
}
}ACauto;
int main()
{
int T;
scanf("%d",&T);
while(T--) {
memset(match,0,sizeof(match));
ACauto.Initial();
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i) {
scanf("%s",s1[i] + 1);
}
scanf("%d%d",&x,&y);
for(int i = 1;i <= x; ++i) {
scanf("%s",s1[0] + 1);
ACauto.Insert(s1[0],i);
}
ACauto.getfail();
for(int i = 1;i <= n; ++i) {
ACauto.query(s1[i],i);
}
int ans = 0;
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j)
if(match[i][j] == x) ans++;
cout<<ans<<endl;
}
return 0;
}