Description

Given an N × M matrix, your task is to find the number of occurences of an X × Y pattern.

Input
The first line contains a single integer t (t ≤ 15), the number of test cases.
For each case, the first line contains two integers N and M (N, M ≤ 1000). The next N lines
contain M characters each.
The next line contains two integers X and Y (X, Y ≤ 100). The next X lines contain Y characters
each.

Output

For each case, output a single integer in its own line, the number of occurrences.

Sample Input

2
1 1
x
1 1
y
3 3
abc
bcd
cde
2 2
bc
cd


Sample Output
0
2

【题意】

  在二维文本串T中查找一个二维模板串P出现了多少次。

【分析】

  拆分模板串P的每一行,建AC自动机。

  拆分文本串T的每一行,在自动机中与P匹配,ct[i][j]表示以点(i,j)为左上角、与P等大的矩形有多少个对应的行与P匹配。
  最后ct[i][j]==P的行数的i,j就是一个匹配点,ans++。
  

  注意:1.原本我在trie的叶子用动态数组维护了一个表示这一行是P的第几行的数组,但是超时了,后来看了LRJ的代码,改成了用一个nt[i]来表示重复的行的下一行,就A了。
  2.注意在ct[i][j]里加的时候判断i,j是否大于0.

代码如下:

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 1010
#define Maxl 110
#define INF 0xfffffff int n,m,l,r;
int ct[Maxn][Maxn],nt[Maxl];
char s[Maxn][Maxn];
char ss[Maxn]; struct node
{
int fail,mark;
int son[];
}t[Maxn*Maxn];int tot; void upd(int x)
{
t[x].mark=;
memset(t[x].son,,sizeof(t[x].son));
} void read_trie(int tk)
{
scanf("%s",s[]+);
int len=strlen(s[]+);
for(int i=;i<=len;i++) ss[i]=s[][len-i+];
int now=;
for(int i=;i<=len;i++)
{
int ind=ss[i]-'a'+;
if(!t[now].son[ind])
{
t[now].son[ind]=++tot;
upd(tot);
}
now=t[now].son[ind];
if(i==len)
{
if(t[now].mark) nt[tk]=t[now].mark;//我好搞笑
t[now].mark=tk;
}
}
} queue<int > q;
void build_AC()
{
while(!q.empty()) q.pop();
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<=;i++)
{
if(t[x].son[i])
{
t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:;
q.push(t[x].son[i]);
}
else t[x].son[i]=t[t[x].fail].son[i];
}
if(t[t[x].fail].mark) t[x].mark=t[t[x].fail].mark;
}
} void add(int x,int y,int z)
{
if(x-z+>=) ct[x-z+][y]++;
if(nt[z]!=) add(x,y,nt[z]);
} void ffind()
{
int now;
memset(ct,,sizeof(ct));
for(int i=;i<=n;i++)
{
now=;
for(int j=m;j>=;j--)
{
now=t[now].son[s[i][j]-'a'+];
if(t[now].mark) add(i,j,t[now].mark);
}
}
int ans=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(ct[i][j]==l) ans++;
printf("%d\n",ans);
} void init()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%s",s[i]+);
tot=;upd();
scanf("%d%d",&l,&r);
memset(nt,,sizeof(nt));
for(int i=;i<=l;i++)
{
read_trie(i);
}
build_AC();
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
ffind();
}
return ;
}

[UVA11019]

2016-07-12 15:37:53

最新文章

  1. 【NDK开发】使用NDK开发android
  2. (旧)子数涵数&#183;PS——冷色调与LOMO
  3. kmp 和boyer-moore
  4. hdu 0-1背包
  5. Eyeshot Ultimate 学习笔记(4)
  6. javascript之String
  7. 排序算法用C++的基本算法实现十个数排序
  8. Angular 非父子组件间的service数据通信
  9. 值得收藏的Mybatis通用Mapper使用大全。
  10. 谁说java里面有返回值的方法必须要有返回值,不然会报错????
  11. 关于CALayer导致的crash问题
  12. java中网络设置代理
  13. 【nginx】配置Nginx实现负载均衡
  14. tomcat中请求参数中文中乱码问题
  15. python解析发往本机的数据包示例 (解析数据包)
  16. 【坚持】Selenium+Python学习之从读懂代码开始 DAY1
  17. jquery 实现抖动效果
  18. first post
  19. jboss 的debug启动4法
  20. Cannot resolve the collation conflict between &quot;Chinese_PRC_CI_AS&quot; and &quot;SQL_L及由于排序规则不同导致查询结果为空的问题

热门文章

  1. VC/MFC 下 递归遍历目录下的所有子目录及文件
  2. Mysql Join语法解析与性能分析详解
  3. 对RecycleView的多种item布局的封装
  4. CentOS 6.7平台Hadoop 1.2.1环境搭建
  5. JS实现图片宽高的等比缩放
  6. TCP/IP 协议理解
  7. 常见sql语句及复杂sql语句记录
  8. 数据库性能高校:CPU使用过高(下)
  9. .NET下的加密解密大全(2):对称加密
  10. JAVAAPI学习之Calendar类;Calendar类set()、add()、roll()方法区别