UVA - 11019(AC自动机)

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

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

Sample Output

0
2

题目大意:给出两个矩阵,问第二个矩阵在第一个矩阵中的出现次数。

解题思路:先将第二个矩阵的每一行加入AC自动机,然后让第一个矩阵中的每一行和第二个矩阵中的第几行匹配,然后用一个二维数组存以第一个矩阵的这一个点开始的矩阵与第二个矩阵匹配的字符串的数量。如果数量达到x,那么表示矩阵匹配。

代码:

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <bitset>
#include <queue>
//#include 
#include <time.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ls root<<1
#define rs root<<1|1
const int inf=1ll*1<<60;
const int maxn=1e4+10;
const int maxm=1e6+10;
int to[maxn][27],cnt[maxn];
int tot,fail[maxn],id[maxn],ans[1100][1100],n,m,x,y;
char arr[1100][1100],str[1010];
vector <int> v[maxn];
void add(char *s,int k)
{
    int now=0;
    for(int i=0;s[i]!='\0';i++){
        int x=s[i]-'a';
        if(!to[now][x])to[now][x]=++tot,v[tot].clear();
        now=to[now][x];
    }
    v[now].push_back(k);
}
void getfail()
{
    queue<int> q;
    for(int i=0;i<26;i++){
        if(to[0][i])q.push(to[0][i]);
    }
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(int i=0;i<26;i++){
            if(to[now][i])fail[to[now][i]]=to[fail[now]][i],q.push(to[now][i]);
            else to[now][i]=to[fail[now]][i];
        }
    }
}
void acm(char *s,int k)
{
    int now=0;
    for(int i=0;s[i]!='\0';i++){
        int x=s[i]-'a';
        now=to[now][x];
        for(int j=now;j;j=fail[j]){
            for(int l=0;l<v[j].size();l++){
                if(k-v[j][l]<0 || i-y+1<0)continue;
                ans[k-v[j][l]][i-y+1]++;
            }
        }
    }
}
signed main()
{
    int t;
    scanf("%lld",&t);
    while(t--){
        memset(ans,0,sizeof ans);
        memset(fail,0,sizeof fail);
        memset(to,0,sizeof to);
        tot=0;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%s",arr[i]);
        }
        scanf("%lld%lld",&x,&y);
        for(int i=1;i<=x;i++){
            scanf("%s",str);
            add(str,i);
        }
        getfail();
        for(int i=1;i<=n;i++){
            acm(arr[i],i);
        }
        int res=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++) if(ans[i][j]==x)res++;
        }
        printf("%lld\n",res);
    }
}

你可能感兴趣的:(AC自动机)