uva11019

来源:互联网 发布:php url 记录跳转设计 编辑:程序博客网 时间:2024/06/05 03:44
// UVa11019 Matrix Matcher// Rujia Liu#include<cstring>#include<queue>#include<cstdio>#include<map>#include<string>using namespace std;const int SIGMA_SIZE = 26;const int MAXNODE = 10000 + 10;void process_match(int pos, int v); // AC自动机每找到一个匹配会调用一次,结束位置为pos,val为vstruct AhoCorasickAutomata {  int ch[MAXNODE][SIGMA_SIZE];  int f[MAXNODE];    // fail函数  int val[MAXNODE];  // 每个字符串的结尾结点都有一个非0的val  int last[MAXNODE]; // 输出链表的下一个结点  int sz;  void init() {    sz = 1;    memset(ch[0], 0, sizeof(ch[0]));  }  // 字符c的编号  int idx(char c) {    return c-'a';  }  // 插入字符串。v必须非0  void insert(char *s, int v) {    int u = 0, 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]));        val[sz] = 0;        ch[u][c] = sz++;      }      u = ch[u][c];    }    val[u] = v;  }  // 递归打印以结点j结尾的所有字符串  void report(int pos, int j) {    if(j) {      process_match(pos, val[j]);      report(pos, last[j]);    }  }  // 在T中找模板  int find(char* T) {    int n = strlen(T);    int j = 0; // 当前结点编号,初始为根结点    for(int i = 0; i < n; i++) { // 文本串当前指针      int c = idx(T[i]);      while(j && !ch[j][c]) j = f[j]; // 顺着细边走,直到可以匹配      j = ch[j][c];      if(val[j]) report(i, j);      else if(last[j]) report(i, last[j]); // 找到了!    }  }  // 计算fail函数  void getFail() {    queue<int> q;    f[0] = 0;    // 初始化队列    for(int c = 0; c < SIGMA_SIZE; c++) {      int u = ch[0][c];      if(u) { f[u] = 0; q.push(u); last[u] = 0; }    }    // 按BFS顺序计算fail    while(!q.empty()) {      int r = q.front(); q.pop();      for(int c = 0; c < SIGMA_SIZE; c++) {        int u = ch[r][c];        if(!u) continue;        q.push(u);        int v = f[r];        while(v && !ch[v][c]) v = f[v];        f[u] = ch[v][c];        last[u] = val[f[u]] ? f[u] : last[f[u]];      }    }  }};AhoCorasickAutomata ac;const int maxn = 1000 + 10;const int maxm = 1000 + 10;const int maxx = 100 + 10;const int maxy = 100 + 10;char text[maxn][maxm], P[maxx][maxy];int repr[maxx]; // repr[i]为模板第i行的“代表元”int next[maxx]; // next[i]为模板中与第i行相等的下一个行编号int len[maxx]; // 模板各行的长度int tr; // 当前文本行编号int cnt[maxn][maxm];void process_match(int pos, int v) {  int pr = repr[v - 1]; // 匹配到得模板行编号  int c = pos - len[pr] + 1;  while(pr >= 0) {    if(tr >= pr) // P的行pr出现在在T的tr行,起始列编号为c      cnt[tr - pr][c]++;    pr = next[pr];  }}int main() {  int T, n, m, x, y;  scanf("%d", &T);  while(T--) {    scanf("%d%d", &n, &m);    for(int i = 0; i < n; i++)      scanf("%s", text[i]);    scanf("%d%d", &x, &y);    ac.init();    for(int i = 0; i < x; i++) {      scanf("%s", P[i]);      len[i] = strlen(P[i]);      repr[i] = i;      next[i] = -1;      for(int j = 0; j < i; j++)        if(strcmp(P[i], P[j]) == 0) {          repr[i] = j;          next[i] = next[j];          next[j] = i;          break;        }      if(repr[i] == i) ac.insert(P[i], i+1);    }    ac.getFail();    memset(cnt, 0, sizeof(cnt));    for(tr = 0; tr < n; tr++)      ac.find(text[tr]);    int ans = 0;    for(int i = 0; i < n-x+1; i++)      for(int j = 0; j < m-y+1; j++)        if(cnt[i][j] == x) ans++;    printf("%d\n", ans);  }  return 0;}

0 0
原创粉丝点击