您的位置:首页 > 其它

UVA 11019 - Matrix Matcher(AC自动机 | hash大法)

2014-08-02 15:09 281 查看


UVA 11019 - Matrix Matcher

题目链接

题意:给定两个矩阵字符串,要求第二个矩阵在第一个矩阵的出现次数

思路:第二个矩阵按行拆分成自动机,然后用第一个矩阵一行一行去匹配,利用一个rc
[M]的数组记录下每个左上角对应位置的成功匹配次数,然后找完后,对于每个位置,如果成功匹配次数为x,那么就是成功匹配上了,ans++

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: