【UVA11019】Matrix Matcher

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.

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 1010
  9 #define Maxl 110
 10 #define INF 0xfffffff
 11 
 12 int n,m,l,r;
 13 int ct[Maxn][Maxn],nt[Maxl];
 14 char s[Maxn][Maxn];
 15 char ss[Maxn];
 16 
 17 struct node
 18 {
 19     int fail,mark;
 20     int son[30];
 21 }t[Maxn*Maxn];int tot;
 22 
 23 void upd(int x)
 24 {
 25     t[x].mark=0;
 26     memset(t[x].son,0,sizeof(t[x].son));
 27 }
 28 
 29 void read_trie(int tk)
 30 {
 31     scanf("%s",s[0]+1);
 32     int len=strlen(s[0]+1);
 33     for(int i=1;i<=len;i++) ss[i]=s[0][len-i+1];
 34     int now=0;
 35     for(int i=1;i<=len;i++)
 36     {
 37         int ind=ss[i]-'a'+1;
 38         if(!t[now].son[ind]) 
 39         {
 40             t[now].son[ind]=++tot;
 41             upd(tot);
 42         }
 43         now=t[now].son[ind];
 44         if(i==len) 
 45         {
 46             if(t[now].mark) nt[tk]=t[now].mark;//我好搞笑
 47             t[now].mark=tk;
 48         }
 49     }
 50 }
 51 
 52 queue<int > q;
 53 void build_AC()
 54 {
 55     while(!q.empty()) q.pop();
 56     q.push(0);
 57     while(!q.empty())
 58     {
 59         int x=q.front();q.pop();
 60         for(int i=1;i<=26;i++) 
 61         {
 62             if(t[x].son[i])
 63             {
 64                 t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:0;
 65                 q.push(t[x].son[i]);
 66             }
 67             else t[x].son[i]=t[t[x].fail].son[i];
 68         }
 69         if(t[t[x].fail].mark) t[x].mark=t[t[x].fail].mark;
 70     }
 71 }
 72 
 73 void add(int x,int y,int z)
 74 {
 75     if(x-z+1>=1) ct[x-z+1][y]++;
 76     if(nt[z]!=0) add(x,y,nt[z]);
 77 }
 78 
 79 void ffind()
 80 {
 81     int now;
 82     memset(ct,0,sizeof(ct));
 83     for(int i=1;i<=n;i++)
 84     {
 85         now=0;
 86         for(int j=m;j>=1;j--)
 87         {
 88             now=t[now].son[s[i][j]-'a'+1];
 89             if(t[now].mark) add(i,j,t[now].mark);
 90         }
 91     }
 92     int ans=0;
 93     for(int i=1;i<=n;i++)
 94      for(int j=1;j<=m;j++)
 95         if(ct[i][j]==l) ans++;
 96     printf("%d\n",ans);
 97 }
 98 
 99 void init()
100 {
101     scanf("%d%d",&n,&m);
102     for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
103     tot=0;upd(0);
104     scanf("%d%d",&l,&r);
105     memset(nt,0,sizeof(nt));
106     for(int i=1;i<=l;i++)
107     {
108         read_trie(i);
109     }
110     build_AC();
111 }
112 
113 int main()
114 {
115     int T;
116     scanf("%d",&T);
117     while(T--)
118     {
119         init();
120         ffind();
121     }
122     return 0;
123 }
[UVA11019]

 

2016-07-12 15:37:53

转载于:https://www.cnblogs.com/Konjakmoyu/p/5663728.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值