Matrix Matcher uva+AC自动机+求子矩阵出现的次数

来源:互联网 发布:打开淘宝跳转到天猫 编辑:程序博客网 时间:2024/05/01 09:04

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

 

解决方案:先把模式串建立一个字典树,有可能会出现相同的,可用vector存模式串的行数,构造fail指针,按行查询,查询的时候,找到一个模式串,在该位置,出现该串的那个子矩阵(与模式串相等的子矩阵)的cont[r][c]++(即行数+1)cont[r][c]表示子矩阵右上角的位置,最后只要累加行等于模式串行数的个数。

code:

#include<iostream>#include<cstdio>#include<queue>#include<cstring>#include<vector>using namespace std;char text[1003][1003];int cnt[1003][1003];int N,M,X,Y,c;struct trie{    struct trie *child[26];    struct trie *fail;    vector<int > v;    trie()    {        for(int i=0; i<26; i++)            child[i]=NULL;        fail=NULL;        v.clear();    }};trie *root;void create(char *word,int k){    int i=0;    trie *p=root;    while(word[i]!='\0')    {        int id=word[i]-'a';        if(p->child[id]==NULL)        {            p->child[id]=new trie();        }        p=p->child[id];        i++;    }    (p->v).push_back(k);}void make_fail(){    queue<trie *>Q;    Q.push(root);///根节点入队    while(!Q.empty())    {        trie *p=Q.front();///出队        Q.pop();        for(int i=0; i<26; i++)        {            if(p->child[i]!=NULL)            {                if(p==root) p->child[i]->fail=root;///若为根节点的孩子,fail指向root                else                {                    trie *temp=p;                    while(temp->fail!=NULL)                    {                        if(temp->fail->child[i]!=NULL)                        {                            p->child[i]->fail=temp->fail->child[i];                            break;                        }                        temp=temp->fail;                    }///沿失败指针找                    if(temp->fail==NULL)                    {                        p->child[i]->fail=root;                    }                }                Q.push(p->child[i]);            }        }    }}void AC_search(){    int i=0;    trie *p=root;    while(text[c][i]!='\0')    {        int id=text[c][i]-'a';        while(p!=root&&p->child[id]==NULL) p=p->fail;        if(p->child[id]!=NULL)        {            p=p->child[id];            p=(p==NULL)?root:p;            trie *temp=p;            while(temp!=root&&(temp->v).size()!=0)            {                for(unsigned int j=0; j<(p->v).size(); j++)                {                    if(c-((p->v)[j])>=0&&X-((p->v)[j])<=N-c)                    {                        cnt[c-(p->v)[j]][i-Y+1]++;                    }                }                temp=temp->fail;            }        }        i++;    }}int main(){    int t;    scanf("%d",&t);    char str[103];    while(t--)    {        root =new trie();        scanf("%d%d",&N,&M);        for(int i=0; i<N; i++)        {            scanf("%s",text[i]);        }        scanf("%d%d",&X,&Y);        for(int i=0; i<X; i++)        {            scanf("%s",str);            create(str,i);        }        make_fail();        memset(cnt,0,sizeof(cnt));        for(c=0; c<N; c++) AC_search();        int sum=0;        for(int i=0; i<N; i++)            for(int j=0; j<M; j++)            {                if(cnt[i][j]==X) sum++;            }        printf("%d\n",sum);    }    return 0;}

0 0
原创粉丝点击