UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
来源:互联网 发布:手机淘宝店铺如何改名 编辑:程序博客网 时间:2024/05/30 05:08
题目大意:给你n*m的一个字符T矩阵,和一个x*y的字符P矩阵,让你找出P矩阵在T矩阵中出现了几次。
思路:把P矩阵一行一行插进去AC自动机,设 cc[ i ][ j ] 表示以T矩阵的第 i 行,第 j 列为左上顶点与P矩阵最多的匹配行数,
那么如果在匹配过程中匹配到的字符是P的某一行末尾的字符,那么就在对应的左上顶点的 cc ++ 即可。最后统计一遍所有顶点的cc,
cc == x 的数量即为匹配次数。这里还有一点需要注意,由于构造AC自动机时,如果两个字符串相同,后面的字符串会覆盖掉前面的,
也就是说 trie 中某个节点可能对应几个P中字符串的结尾,所以这里我直接用 vector 来存 val 信息了。
这题说实话这题自己想的时候,没有思路,看了书上的思路才写的,发现AC自动机好多都和DP结合起来,这题赞一个!
错了两次才AC的,第一遍是RE,可能是由于我把变量都开在 struct 里的原因,以后干脆直接就放外面好了,之后 WA 了,然后对照模板,发现原来是
get_fail 那里的 while 我把 !ch[ pre ][ i ] 写成 ch[ pre ][ i ]了,又是小细节问题。幸好改过来后就直接A了。。 = =
思路:把P矩阵一行一行插进去AC自动机,设 cc[ i ][ j ] 表示以T矩阵的第 i 行,第 j 列为左上顶点与P矩阵最多的匹配行数,
那么如果在匹配过程中匹配到的字符是P的某一行末尾的字符,那么就在对应的左上顶点的 cc ++ 即可。最后统计一遍所有顶点的cc,
cc == x 的数量即为匹配次数。这里还有一点需要注意,由于构造AC自动机时,如果两个字符串相同,后面的字符串会覆盖掉前面的,
也就是说 trie 中某个节点可能对应几个P中字符串的结尾,所以这里我直接用 vector 来存 val 信息了。
这题说实话这题自己想的时候,没有思路,看了书上的思路才写的,发现AC自动机好多都和DP结合起来,这题赞一个!
错了两次才AC的,第一遍是RE,可能是由于我把变量都开在 struct 里的原因,以后干脆直接就放外面好了,之后 WA 了,然后对照模板,发现原来是
get_fail 那里的 while 我把 !ch[ pre ][ i ] 写成 ch[ pre ][ i ]了,又是小细节问题。幸好改过来后就直接A了。。 = =
代码如下:
#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<algorithm>using namespace std;const int MAX_NODE = 11111;const int SIGMA_SIZE = 26;char t[1111][1111],p[111][111];int cc[1111][1111];int ch[MAX_NODE][SIGMA_SIZE];int fail[MAX_NODE];int tot;vector <int> val[MAX_NODE];struct Ac{ void init() { memset(ch[0],0,sizeof(ch[0])); tot = 1; val[0].clear(); } int idx(char c) { return c - 'a'; } void insert(char *s,int len,int id) { int u = 0; for(int i = 0;i<len;i++) { int c = idx(s[i]); if(!ch[u][c]) { memset(ch[tot],0,sizeof(ch[tot])); val[tot].clear(); ch[u][c] = tot++; } u = ch[u][c]; } val[u].push_back(id); } void get_fail() { fail[0] = 0; queue <int> q; for(int i = 0;i<SIGMA_SIZE;i++) if(ch[0][i]) { fail[ch[0][i]] = 0; q.push(ch[0][i]); } while(!q.empty()) { int u = q.front(); q.pop(); for(int i = 0;i<SIGMA_SIZE;i++) { int v = ch[u][i]; if(!v) { ch[u][i] = ch[fail[u]][i]; continue; } q.push(v); int j = fail[u]; while(j && !ch[j][i]) j = fail[j]; j = ch[j][i]; fail[v] = j; } } } int find(int x,int y,int n,int m) { memset(cc,0,sizeof(cc)); int pre = 0; for(int i = 1;i<=n;i++) for(int j = 0;j<m;j++) { int c = idx(t[i][j]); pre = ch[pre][c]; for(int pos = 0;pos < val[pre].size();pos ++) { int ii = i - (val[pre][pos] - 1); int jj = j - (y - 1); cc[ii][jj]++; } } int ans = 0; for(int i = 1;i<=n;i++) for(int j = 0;j<m;j++) if(cc[i][j] == x) ans ++; return ans; }}ac;int main(){ int _; scanf("%d",&_); while(_--) { ac.init(); int n,m; scanf("%d%d",&n,&m); for(int i = 1;i<=n;i++) scanf("%s",t[i]); int x,y; scanf("%d%d",&x,&y); for(int i = 1;i<=x;i++) { scanf("%s",p[i]); ac.insert(p[i],y,i); } ac.get_fail(); printf("%d\n",ac.find(x,y,n,m)); } return 0;}
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- UVa 11019 Matrix Matcher AC自动机 二维匹配
- uva 11019 Matrix Matcher (ac自动机二维匹配)
- UVA 11019 Matrix Matcher(二维矩阵匹配ac自动机)
- UVA - 11019 Matrix Matcher (AC自动机(二维匹配) + dp)
- 矩阵匹配 AC自动机 或 二维Hash UVa 11019 - Matrix Matcher
- UVA 11019(Matrix Matcher-vector从迭代器中取值,AC自动机匹配字符矩阵)
- UVA 11019 Matrix Matcher(AC自动机矩阵匹配)
- UVA 11019 Matrix Matcher(AC自动机:矩阵匹配)
- UVA 11019 Matrix Matcher AC自动机字符串矩阵匹配
- UVa:11019 Matrix Matcher(AC自动机)
- uva 11019 - Matrix Matcher(AC自动机)
- uva 11019 - Matrix Matcher --AC自动机
- UVA-11019 - Matrix Matcher(AC自动机)
- UVA 11019 Matrix Matcher(AC自动机)
- AC自动机(Matrix Matcher,UVA 11019)
- UVA-11019Matrix Matcher(AC自动机)
- uva11019 - Matrix Matcher 二维矩阵匹配 AC自动机
- 重新校正节点运行的实例
- 进程nice值曲线图
- 线程Dump
- 抓取dump文件
- ubuntu查找命令集
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- OCP-1Z0-051-V9.02-88题
- VC API常用函数简单例子大全(1-89)
- 什么是卓越和激情的游戏公司-“部落冲突”开发商Supercell的诞生之路
- Linux文件编程,时间编程——系统调用-文件访问
- Qt学习第四天
- 再谈雅克比矩阵---在feature learning中的作用
- 毕业季之找工作——面试小总结+自我激励
- 嵌入式学习步骤