UVA11019 Matrix Matcher (AC自动机)

二维的矩阵匹配,把模式矩阵按列拆开构造AC自动机,记录行号(为了缩点判断)。

把T矩阵按行匹配,一旦匹配成功,在假想的子矩阵左上角位置加一。最后统计总数。

因为所有模式串长度一样,不用维护last数组。

模式串可能有重复,结点要用vector来存。

HASH出奇迹,快得不行。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1001,maxm = 101;
char Text[maxn][maxn], pattern[maxm];
const int maxnds = maxm*maxm, sigma_size = 26;
int nds;
int ch[maxnds][sigma_size];
int f[maxnds];
vector<int> val[maxnds];

void bfs()
{
    f[0] = 0; 
    queue<int> q;
    for(int c = 0; c < sigma_size; c++){
        int u = ch[0][c];
        if(u){ q.push(u); f[u] = 0;} 
    }
    while(q.size()){
        int r = q.front(); q.pop();
        for(int c = 0; c < sigma_size; c++){
            int u = ch[r][c];
            if(!u) { ch[r][c] = ch[f[r]][c]; continue; }
            q.push(u);
            int v = f[r];
            while(v && !ch[v][c]) v = f[v];
            f[u] = ch[v][c];
        }
    }
}

#define idx(x) x-'a';
void add(char *s,int i)
{
    int n = strlen(s), u = 0;
    for(int i = 0; i < n; i++){
        int c = idx(s[i]);
        if(!ch[u][c]){
            u = ch[u][c] = nds++;
            memset(ch[u],0,sizeof(ch[u]));
            val[u].clear();
        }else u = ch[u][c];
    }
    val[u].push_back(i);
}

void init()
{
    nds = 1;
    memset(ch[0],0,sizeof(ch[0]));
    val[0].clear();
}

int cnt[maxn][maxn];
int N,M;
int X,Y;

void cal(int i,int j)
{
    if(i>=0) cnt[i][j]++;
}

void Find(char *T,int R)
{
    int n = strlen(T), u = 0;
    for(int i = 0; i < n; i++){
        int c = idx(T[i]);
        u = ch[u][c];
        if(val[u].size() ){
            for(auto it:val[u]){
                cal(R-it+1,i-Y+1);
            }
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        init();
        scanf("%d%d",&N,&M);
        for(int i = 0; i < N; i++){
            scanf("%s",Text[i]);
        }
        scanf("%d%d",&X,&Y);
        for(int i = 1; i <= X; i++){
            scanf("%s",pattern);
            add(pattern,i);
        }
        bfs();
        for(int i = 0; i < N; i++){
            Find(Text[i],i);
        }
        int ans = 0;
        for(int i = 0; i < N; i++){
            for(int j = 0; j < M; j++){
                if(cnt[i][j]){
                    if(cnt[i][j] == X) ans++;
                    cnt[i][j] = 0;
                }
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4798348.html