Uva 11019 Matrix Matcher

看起来像是二维的AC自动机。。。坑了我2天。。。。0.000秒WA怎么都过不了。。。

找AC的程序对拍也找不到错误,最后直接交AC的程序也是WA。。。估计是数据出问题了抓狂

# ProblemVerdictLanguageRun TimeSubmission Date
127262 77 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-25 03:23:36
12726261 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-25 03:16:56
12726200 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-25 03:02:23
12726148 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-25 02:25:17
12723738 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-24 14:31:03
12723673 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-24 14:20:16
12723224 11019 Matrix Matcher Wrong answer C++ 0.000 2013-11-24 12:43:50

题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次.

分析:要想整个矩阵匹配,至少各行都得匹配。所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行逐一匹配,找到P中每一行的所有匹配点。

只要在匹配时做一些附加操作,就可以把匹配出来的单一的行拼成矩形。用一个d[r][c]表示T中一(r,c)为右上角,与P等大的矩形中有多少个完整的行和P对应位置的行完全相同.当P的第i行出现在T的第r行,起始列编号为c时,意味着d[r-i][c]应当加1.所有匹配结束后,d[r][c]=X的那些就是一个二维匹配点.

注意:模式串有可能相同.

Time Limit: 3000MSMemory Limit: Unknown64bit IO Format: %lld & %llu

[Submit]   [Go Back]   [Status]  

Description

Download as PDF

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 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                               Output for Sample Input

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

0

2

 


                                                  




                                   


Problem Setter: Rujia Liu, EPS

Special Thanks: Wenbin Tang

 

Warming: The judge input file size is about 7 MB. So please make sure that you use a fast IO function (eg. scanf()) to read input.

 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

const int maxn=11000;

int m,n,x,y;
char T[1100][1100],P[110][110];
int chd[maxn][26],sz,val[maxn],last[maxn],f[maxn];
int ct[1100][1100];
vector<int> next[maxn];

int init()
{
    sz=1;
    memset(chd[0],0,sizeof(chd[0]));
    memset(ct,0,sizeof(ct));
    memset(val,0,sizeof(val));
    memset(last,0,sizeof(last));
    memset(f,0,sizeof(f));
    for(int i=0;i<10000;i++) next[i].clear();
}

int insert(char *p,int i)
{
    int u=0;
    for(;*p;p++)
    {
        if(!chd[u][*p-'a'])
        {
            memset(chd[sz],0,sizeof(chd[sz]));
            chd[u][*p-'a']=sz++;
        }
        u=chd[u][*p-'a'];
    }
    val[u]=i;
    next[u].push_back(i);
}

int getFail()
{
    queue<int> q;
    f[0]=0;
    for(int c=0;c<26;c++)
    {
        int u=chd[0][c];
        if(u)
        {
            f[u]=last[u]=0;
            q.push(u);
        }
    }
    while(!q.empty())
    {
        int r=q.front(); q.pop();
        for(int c=0;c<26;c++)
        {
            int u=chd[r][c];
            if(!u)
            {
                chd[r][c]=chd[f[r]][c];
                continue;
            }
            q.push(u);
            int v=f[r];
            while(v&&!chd[v][c]) v=f[v];
            f[u]=chd[v][c];
            last[u]=val[f[u]]?f[u]:last[f[u]];
        }
    }
}

void solve(int u,int line,int lie)
{
    if(val[u])
    {
        int t=next[u].size();
        for(int i=0;i<t;i++)
        {
            if(line-next[u][i]+1>=0)
                ct[line-next[u][i]+1][lie-y+1]++;
        }
        solve(last[u],line,lie);
    }
}

void find(char* T,int L)
{
    int j=0;
    for(int i=0;i<m;i++)
    {
        int c=T[i]-'a';
        j=chd[j][c];
        if(val[j]) solve(j,L,i);
        else if(last[j]) solve(last[j],L,i);
    }
}

int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%s",T[i]);
        init();
        scanf("%d%d",&x,&y);
        for(int i=1;i<=x;i++)
        {
            scanf("%s",P[i]);
            insert(P[i],i);
        }
        getFail();
        for(int i=0;i<n;i++)
        {
            find(T[i],i);
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
            //    cout<<ct[i][j]<<" ";
                if(ct[i][j]==x) ans++;
            }
        //    cout<<endl;
        }
        printf("%d\n",ans);
    }
    return 0;
}







  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值