您的位置:首页 > 其它

矩阵匹配 AC自动机 或 二维Hash UVa 11019 - Matrix Matcher

2015-09-24 23:29 387 查看
题意:给出一个n*m的字符矩阵T,你的任务是找出给定的x*y的字符矩阵P在T中出现了多少次.

分析:要想整个矩阵匹配,至少各行都得匹配。所以先把P的每行看做一个模式串构造出AC自动机,然后在T中的各行逐一匹配,找到P中每一行的所有匹配点。

只要在匹配时做一些附加操作,就可以把匹配出来的单一的行拼成矩形。用一个count[r][c]表示T中一(r,c)为右上角,与P等大的矩形中有多少个完整的行和P对应位置的行完全相同.当P的第i行出现在T的第r行,起始列编号为c时,意味着count[r-i][c]应当加1.所有匹配结束后,count[r][c]=X的那些就是一个二维匹配点.

注意:模式串有可能相同,因此需要一个链表来相同的模式串.

#include <cstdio>  
#include <cstring>  
#include <queue>  
using namespace std;  
  
const int MAXNODE = 10005;  
const int SIGMA_SIZE = 127;  
const int N = 1005;  
const int M = 105;  
  
struct AutoMac {  
  
    int ch[MAXNODE][SIGMA_SIZE];  
    int val[MAXNODE][105];  
    int vn[MAXNODE];  
    int next[MAXNODE];  
    int last[MAXNODE];  
    int sz;  
  
    int n, m, x, y;  
    char nm

, xy[M];  
    int rc

;  
  
    void init() {  
    sz = 1;  
    memset(ch[0], 0, sizeof(ch[0]));  
    }  
  
    int idx(char c) {  
    return c;  
    }  
  
    void insert(char *s, int v) {  
    int u = 0;  
    int n = strlen(s);  
    for (int i = 0; i < n; i++) {  
        int c = idx(s[i]);  
        if (!ch[u][c]) {  
        memset(ch[sz], 0, sizeof(ch[sz]));  
        memset(val[sz], 0, sizeof(val[sz]));  
        vn[sz] = 0;  
        ch[u][c] = sz++;  
        }  
        u = ch[u][c];  
    }  
    val[u][vn[u]++] = v;  
    }  
  
    void getnext() {  
    next[0] = 0;  
    queue<int> Q;  
    for (int c = 0; c < SIGMA_SIZE; c++) {  
        int u = ch[0][c];  
        if (u) {next[u] = 0; Q.push(u); last[u] = 0;}  
    }  
    while (!Q.empty()) {  
        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[next[r]][c];  
            continue;  
        }  
        Q.push(u);  
        int v = next[r];  
        while (v && !ch[v][c]) v = next[v];  
        next[u] = ch[v][c];  
        last[u] = val[next[u]] ? next[u] : last[next[u]];  
        }  
    }  
    }  
  
    void print(int r, int c, int j) {  
    if (j) {  
        for (int i = 0; i < vn[j]; i++) {  
        if (r - val[j][i] >= 0)  
            rc[r - val[j][i]][c]++;  
        }  
        print(r, c, last[j]);  
    }  
    }  
  
    void find(int row) {  
    int u = 0;  
    int n = strlen(nm[row]);  
    for (int i = 0; i < n; i++) {  
        int c = idx(nm[row][i]);  
        u = ch[u][c];  
        if (val[u]) print(row, i - y + 1, u);  
        else if (last[u]) print(row, i - y + 1, last[u]);  
    }  
    }  
      
    void solve() {  
    memset(rc, 0, sizeof(rc));  
    scanf("%d%d", &n, &m);  
    for (int i = 1; i <= n; i++)  
        scanf("%s", nm[i]);  
    scanf("%d%d", &x, &y);  
    for (int i = 1; i <= x; i++) {  
        scanf("%s", xy);  
        insert(xy, i);  
    }  
    getnext();  
    for (int i = 1; i <= n; i++)  
        find(i);  
    int ans = 0;  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < m; j++) {  
        if (rc[i][j] == x)  
            ans++;  
        }  
    }  
    printf("%d\n", ans);  
    }  
};  
  
AutoMac gao;  
  
int main() {  
    int t;  
    scanf("%d", &t);  
    while (t--) {  
    gao.init();  
    gao.solve();  
    }  
    return 0;  
}



二维Hash

#include <cstdio>  
#include <cstring>  
  
typedef unsigned long long ull;  
  
const ull X1 = 100000007, X2 = 1000000007;  
  
const int N = 1005;  
const int M = 105;  
  
int t, n, m, x, y;  
char a

, b[M][M];  
ull H

;  
  
ull gethash() {  
    ull ans = 0;  
    for (int i = 0; i < x; i++) {  
    ull u = 0;  
    for (int j = 0; j < y; j++)  
        u = u * X1 + b[i][j];  
    ans = ans * X2 + u;  
    }  
    return ans;  
}  
  
int solve() {  
    ull u = gethash(), Hp = 1;  
    for (int i = 0; i < y - 1; i++)  
    Hp *= X1;  
    for (int i = 0; i < n; i++) {  
    ull sum = 0;  
    for (int j = 0; j < y - 1; j++)  
        sum = sum * X1 + a[i][j];  
    for (int j = y - 1; j < m; j++) {  
        sum = sum * X1 + a[i][j];  
        H[i][j - y + 1] = sum;  
        sum -= Hp * a[i][j - y + 1];  
    }  
    }  
    int ans = 0;  
    Hp = 1;  
    for (int i = 0; i < x - 1; i++)  
    Hp *= X2;  
    for (int j = 0; j < m - y + 1; j++) {  
    ull sum = 0;  
    for (int i = 0; i < x - 1; i++)  
        sum = sum * X2 + H[i][j];  
    for (int i = x - 1; i < n; i++) {  
        sum = sum * X2 + H[i][j];  
        if (sum == u) ans++;  
        sum -= Hp * H[i - x + 1][j];  
    }  
    }  
    return ans;  
}  
  
int main() {  
    scanf("%d", &t);  
    while (t--) {  
    scanf("%d%d", &n, &m);  
    for (int i = 0; i < n; i++)  
        scanf("%s", a[i]);  
    scanf("%d%d", &x, &y);  
    for (int i = 0; i < x; i++)  
        scanf("%s", b[i]);  
    printf("%d\n", solve());  
    }  
    return 0;  
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: