【uva11019-Matrix Matcher】AC自动机+优化+记录

http://acm.hust.edu.cn/vjudge/problem/33057

题意:在二维文本串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<queue>
  6 #include<vector>
  7 using namespace std;
  8
  9 int n,m,num,ans;
 10 int ct[1100][1100],nt[110];
 11 char s[1100][1100],ss[1100][1100];
 12 struct node{
 13     int son[30];
 14     int fail,ed;
 15 }a[110*110];
 16 queue<int> q;
 17
 18 void clear(int x)
 19 {
 20     a[x].fail=a[x].ed=0;
 21     memset(a[x].son,0,sizeof(a[x].son));
 22 }
 23
 24 void trie(char *c,int id)
 25 {
 26     int l=strlen(c);
 27     int x=0;
 28     for(int i=0;i<l;i++)
 29     {
 30         int t=c[i]-‘a‘+1;
 31         if(!a[x].son[t])
 32         {
 33             num++;
 34             clear(num);
 35             a[x].son[t]=num;
 36         }
 37         x=a[x].son[t];
 38     }
 39     if(!a[x].ed) a[x].ed=id;
 40 }
 41
 42 void buildAC()
 43 {
 44     while(!q.empty()) q.pop();
 45     for(int i=1;i<=26;i++)
 46         if(a[0].son[i]) q.push(a[0].son[i]);
 47     while(!q.empty())
 48     {
 49         int x=q.front();q.pop();
 50         int fail=a[x].fail;
 51         for(int i=1;i<=26;i++)
 52         {
 53             int y=a[x].son[i];
 54             if(y)
 55             {
 56                 a[y].fail=a[fail].son[i];
 57                 q.push(y);
 58             }
 59             else a[x].son[i]=a[fail].son[i];
 60         }
 61     }
 62 }
 63
 64 void find(char *c,int id)
 65 {
 66     int l=strlen(c);
 67     int x=0;
 68     for(int i=0;i<l;i++)
 69     {
 70         int t=c[i]-‘a‘+1;
 71         if(!a[x].son[t]) x=0;
 72         x=a[x].son[t];
 73         int x0=id,y0=(i+1)-m+1;
 74         int p=a[x].ed;
 75         while(p)
 76         {
 77             int xx=x0-p+1,yy=y0;
 78             if(xx>=1 && yy>=1)//注意!!没有就WA!!
 79             {
 80                 ct[xx][yy]++;
 81                 if(ct[xx][yy]>=n) ans++;
 82             }
 83             p=nt[p];
 84         }
 85     }
 86 }
 87
 88 int main()
 89 {
 90     freopen("a.in","r",stdin);
 91     freopen("a.out","w",stdout);
 92     int T;
 93     scanf("%d",&T);
 94     while(T--)
 95     {
 96         num=ans=0;
 97         clear(0);
 98         memset(ct,0,sizeof(ct));
 99         memset(nt,0,sizeof(nt));//用nt数组(next)优化,不然就TLE。
100         int x,y;
101         scanf("%d%d",&x,&y);
102         for(int i=1;i<=x;i++)
103         {
104             scanf("%s",ss[i]);
105         }
106         scanf("%d%d",&n,&m);
107         for(int i=1;i<=n;i++)
108         {
109             scanf("%s",s[i]);
110             trie(s[i],i);
111         }
112         for(int i=1;i<=n;i++)
113             for(int j=i+1;j<=n;j++)
114             {
115                 if(strcmp(s[i],s[j])==0) {nt[i]=j;break;}
116             }
117         buildAC();
118         for(int i=1;i<=x;i++) find(ss[i],i);
119         printf("%d\n",ans);
120     }
121     return 0;
122 }
时间: 2024-11-10 11:41:31

【uva11019-Matrix Matcher】AC自动机+优化+记录的相关文章

uva 11019 - Matrix Matcher(AC自动机)

题目链接:uva 11019 - Matrix Matcher 题目大意:给出一个n?m的字符矩阵T,要求找出给定r?c的字符矩阵P在T中出现的次数. 解题思路:对P矩阵中的每一行做一个字符串,形成一个字符串集合.构建AC自动机,然后对T矩阵中的每一行进行一次查找,对应出现在该字符串中的子串对应位置+1,如果有一个位置上r次匹配,那么就存在一个匹配矩阵. #include <cstdio> #include <cstring> #include <queue> #inc

AC 自动机优化

AC 自动机优化 今天来小谈一下AC自动机的优化. 1:在 trie 树中被搜过的点不用再搜第二遍,标记一下,因为答案已经统计入答案中. 2:有点类似路径压缩的感觉. 1 if (int y=e[x].nxt[i]) 2 { 3 e[e[x].nxt[i]].fail=e[e[x].fail].nxt[i]; 4 q[++tail]=y; 5 } 6 else e[x].nxt[i]=e[e[x].fail].nxt[i]; 如果  nxt  数组为空,则 假设个虚拟节点,然后将它连入下一个 

AC自动机解题记录

1.HDU 2222 Keywords Search 模板题 1 #include <bits/stdc++.h> 2 #define fir first 3 #define sec second 4 #define EPS 1e-12 5 using namespace std; 6 7 typedef long long LL; 8 typedef pair<int , int > pii; 9 const int MAXN=5e5+5; 10 11 struct Trie{

UVA11019 Matrix Matcher

思路 AC自动机匹配二维模式串的题目 因为如果矩形匹配,则每一行都必须匹配,考虑对于一个点,设count[i][j]记录以它为左上角的与模式矩形大小相同的矩形中有多少行和模式矩形匹配 然后把模式矩形的每一行插入AC自动机中,把文本矩形的每一行在上面跑,如果文本矩形第i行和模式矩形第c行匹配,匹配位置是j,则更新 counts[i-c+1][j+1-y+1] 最后每个count[i][j]等于x的(i,j)就是一个符合条件的点 小心重复的模式串. 代码 #include <cstdio> #in

[AC自动机+dp+记录路径] hdu 2825 Ring

题意: 给N个长度,M个单词,每个单词有权值 输出长度不大于N的权值和最大的单词 代价相同输出长度短的,长度相同输出字典序最小 思路: 开一个字符串数组,暴力存储每个节点的单词! 其他思路和dp都一样 注意:如果和为零的话输出空串. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue"

HDU 5384——Danganronpa——————【AC自动机】

Danganronpa Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 582    Accepted Submission(s): 323 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft

HDU 2896 病毒侵袭 (AC自动机模板)

病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 13063    Accepted Submission(s): 3378 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年一遇的世界奇观,那是多么幸福的事

HDU 3341 Lost&#39;s revenge(AC自动机+状压DP)

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 4548    Accepted Submission(s): 1274 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

bzoj4231回忆树——AC自动机

bzoj4231 回忆树 给定一颗Trie树,每次询问u到v的路径上构成的字符串包含了给定模式串T多少次. 思路 考虑离线之后对于所有的模式串建立AC自动机,考虑跨过lca的串范围有限,直接暴力kmp即可. 然后我们就将一次询问拆成了两条链了,可以将每次询问挂在链上然后离线去dfs,每次dfs时将这个节点添加进AC自动机匹配,对于一段u到v的链,我们在链头的某一个位置减去之前不合法的匹配数量,再在链尾加上总的匹配数量就好了. 如何用ac自动机来记录某个固定的串匹配了多少次的话,可以建立fail树