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 <random>
#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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章