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>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
int Trie[10100][26],fail[10100],counts[1010][1010],root,Nodecnt,x,y,n,m;
char s[1010][1010],t[110][110];
vector<int> isend[10100];
void insert(char *s,int len,int inq){
    int o=root;
    for(int i=0;i<len;i++){
        if(!Trie[o][s[i]-'a'])
            Trie[o][s[i]-'a']=++Nodecnt;
        o=Trie[o][s[i]-'a'];
    }
    isend[o].push_back(inq);
}
queue<int> q;
void build_AC(void){
    for(int i=0;i<26;i++){
        if(Trie[root][i]){
            fail[Trie[root][i]]=root;
            q.push(Trie[root][i]);
        }
    }
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(Trie[x][i]){
                fail[Trie[x][i]]=Trie[fail[x]][i];
                q.push(Trie[x][i]);
            }
            else
                Trie[x][i]=Trie[fail[x]][i];
        }
    }
}
void query(char *s,int len,int inq){
    int o=root;
    for(int i=0;i<len;i++){
        o=Trie[o][s[i]-'a'];
        int p=o;
        while(p){
            if((isend[p].size()))
                for(int j=0;j<isend[p].size();j++)
                    if((inq-isend[p][j]+1)>=1&&(i+1-y+1>=1))
                        counts[inq-isend[p][j]+1][i+1-y+1]++;
            p=fail[p];
        }
    }
}
void init(void){
    memset(Trie,0,sizeof(Trie));
    memset(fail,0,sizeof(fail));
    memset(counts,0,sizeof(counts));
    for(int i=0;i<=Nodecnt;i++)
        isend[i].clear();
    Nodecnt=0;
    root=0;
}
int main(){
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    int T;
    Nodecnt=0;
    root=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]);
        scanf("%d %d",&x,&y);
        for(int i=1;i<=x;i++){
            scanf("%s",t[i]);
            insert(t[i],y,i);
        }
        build_AC();
        for(int i=1;i<=n;i++){
            query(s[i],m,i);
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(counts[i][j]==x)
                    ans++;
        printf("%d\n",ans);
        init();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/dreagonm/p/10694895.html

时间: 2024-11-12 15:35:59

UVA11019 Matrix Matcher的相关文章

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

UVA - 11019 Matrix Matcher hash+KMP

题目链接:https://vjudge.net/problem/UVA-11019 题解: 赶着回寝室 明天写题解 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii

UVA 11019 Matrix Matcher 二维的字符串匹配 ac自动机

只要把每行的模版串插到ac自动机,然后匹配行,每次匹配成功,那一行对应的字符矩阵的左上角的计数器+1,最后统计下计数器矩阵有多少个左上角是行数的就可以了. 思路很简单,但想法很好,但要注意模版上有两行是一样的,插入到ac自动机的时候会插到同一个结点上,为了区分,我还是谨慎地开了个vector,然后1A了. #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,s

uva 11019 Matrix Matcher

题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次. 思路:要想整个矩阵匹配,至少各行都得匹配.所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行逐一匹配,找到P中每一行的所有匹配点. 只要在匹配时做一些附加操作,就可以把匹配出来的单一的行拼成矩形.用一个count[r][c]表示T中一(r,c)为右上角,与P等大的矩形中有多少个 完整的行和P对应位置的行完全相同.当P的第i行出现在T的第r行,起始列编号为c时,意味着count[r-i][c

UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次出现的位置.如果repr[i] == i,说明这个模式串之前没有重复过,可以加进自动机里去.有重复的话,把这些重复的模式串组织成一个链表,用next把它们连接起来. 所以在统计cnt的时候,匹配到的模式串可能会作为匹配的第i行,也可能是next[i]行,next[next[i]]行等等. 1 #in

AC自动机(二维) UVA 11019 Matrix Matcher

题目传送门 题意:训练之南P218 分析:一行一行的插入,一行一行的匹配,当匹配成功时将对应子矩阵的左上角位置cnt[r][c]++;然后统计 cnt[r][c] == x 的数量 #include <bits/stdc++.h> using namespace std; const int N = 1e3 + 5; const int NODE = 1e4 + 5; const int SIZE = 26; char mat1[N][N], mat2[105][105]; int cnt[N

UVa 11019 Matrix Matcher - Hash

题目传送门 快速的vjudge传送门 快速的UVa传送门 题目大意 给定两个矩阵S和T,问T在S中出现了多少次. 不会AC自动机做法. 考虑一维的字符串Hash怎么做. 对于一个长度为$l$的字符串$s$,它的Hash值$hash(s) = \sum_{i = 1}^{l}x^{l - i}s_{i}$. 对于二维的情况,我们就取两个基,$x, y$,对于一个$n\times m$的矩阵$A$的Hash值可以表示为 $hash(A) = \sum_{i = 1}^{n}\sum_{j = 1}^

UVA 11019(Matrix Matcher-vector从迭代器中取值,AC自动机匹配字符矩阵)

Problem H Matrix Matcher Input: Standard Input Output: Standard Output 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 e

UVA 11019

Problem HMatrix MatcherInput: Standard Input Output: Standard Output 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 eac