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

Matrix Matcher UVA - 11019
题意:给你两个矩阵,在一个矩阵中查找另一个矩阵出现了多少次。


解题思路:hash或者AC自动机。这里讲AC自动机做法。

为避免歧义,以下数组皆从0开始
设数组ans[i][j]储存以点(i,j)为左上角能满足匹配矩阵的最大行数。
对每一行建立AC自动机,去匹配模式串。
如果匹配成功,那么就有

ans[当前行数-匹配成功的行数][当前点在该行位置-匹配矩阵的长度]++

坑点:匹配矩阵有可能多行相同,需要开vector去储存字典树中的位置对应的行数。


AC代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
//#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int mod=1000007;
const int maxn=2e6+10;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
char s[1005][1005],t[105][105];
int trie[10005][30],fail[10005],ans[1005][1005],tot;
vector<int>v[1005];
void add_trie(char *str,int k){
    int len=strlen(str);
    int pos=0;
    for (int i=0;i<len;i++){
        if (!trie[pos][str[i]-'a']) {
            trie[pos][str[i]-'a']=++tot;
            v[trie[pos][str[i]-'a']].clear();
        }
        pos=trie[pos][str[i]-'a'];
    }
    v[pos].push_back(k);
}
void get_fail(){
    queue<int>q;
    fail[0]=0;
    for (int i=0;i<26;i++){
        if (trie[0][i]){
            q.push(trie[0][i]);
            fail[trie[0][i]]=0;
        }
    }
    while (!q.empty()){
        int pos=q.front();
        q.pop();
        for (int i=0;i<26;i++){
            if (trie[pos][i]){
                q.push(trie[pos][i]);
                fail[trie[pos][i]]=trie[fail[pos]][i];
            } else trie[pos][i]=trie[fail[pos]][i];
        }
    }
}
void build_trie(int x){
    MT(trie,0);
    MT(fail,0);
    MT(ans,0);
    v[0].clear();
    tot=0;
    for (int i=0;i<x;i++){
        add_trie(t[i],i);
    }
    get_fail();
}
void solve(int k,int lent){
    int len=strlen(s[k]);
    int pos=0;
    for (int i=0;i<len;i++){
        pos=trie[pos][s[k][i]-'a'];
        for (int j=pos;j;j=fail[j]){
            for (int w=0;w<v[j].size();w++){
                if (k-v[j][w]<0||i-lent+1<0) continue;
                ans[k-v[j][w]][i-lent+1]++;
            }
        }
    }
}
int check(int m,int n,int x,int y){
    int k=0;
    for (int i=0;i+x-1<m;i++){
        for (int j=0;j+y-1<n;j++){
            if (ans[i][j]==x) k++;
        }
    }
    return k;
}
int main(){
    int T;scanf("%d",&T);
    while (T--){
        int m,n,x,y;
        scanf("%d%d",&m,&n);
        for (int i=0;i<m;i++){
            scanf("%s",s[i]);
        }
        scanf("%d%d",&x,&y);
        for (int i=0;i<x;i++){
            scanf("%s",t[i]);
        }
        build_trie(x);
        for (int i=0;i<m;i++) solve(i,y);
        printf("%d\n",check(m,n,x,y));
    }
    return 0;
}

你可能感兴趣的:(Matrix Matcher UVA - 11019 (二维AC自动机))