UVA11019 Matrix Matcher

题目大意:给你一个矩阵T,问另一个矩阵P在这个矩阵T中出现过几次

可以用hash水,常数还小,双hash还卡不了

正解是把P每一行作为一个串,建一个AC自动机

用T的每一行去匹配,维护tot[i][j]表示T中左上角为i,j的T大小的矩阵,出现了T中的多少行

答案为tot[i][j] = x的i,j个数

各种卡常+反复提交,终于过了

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <vector>
  6 #define min(a, b) ((a) < (b) ? (a) : (b))
  7 #define max(a, b) ((a) > (b) ? (a) : (b))
  8 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
  9 inline void swap(int &a, int &b)
 10 {
 11     long long tmp = a;a = b;b = tmp;
 12 }
 13 inline void read(int &x)
 14 {
 15     x = 0;char ch = getchar(), c = ch;
 16     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 17     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 18     if(c == '-') x = -x;
 19 }
 20 
 21 const int INF = 0x3f3f3f3f;
 22 const int MAXNODE = 10000 + 1;
 23 const int MAXLEN = 1000 + 1;
 24 
 25 int t,n,m,x,y,ans,cnt, tag[MAXNODE], ch[27][MAXNODE], tot[MAXLEN][MAXLEN], fail[MAXNODE], last[MAXNODE];
 26 char T[MAXLEN][MAXLEN], P[MAXLEN][MAXLEN];
 27 std::vector<int> node[MAXNODE]; 
 28 
 29 int bq[MAXNODE], btot;
 30 void insert(int x)
 31 {
 32     int now = 0;
 33     for(int i = 1;P[x][i] != '';++ i)
 34     {
 35         int &tmp = ch[P[x][i] - 'a' + 1][now];
 36         if(tmp) now = tmp;
 37         else now = tmp = ++ cnt;
 38     } 
 39     ++ tag[now], node[now].push_back(x); 
 40     bq[++ btot] = now;
 41 } 
 42 
 43 int q[MAXNODE], he, ta;
 44 
 45 void build()
 46 {
 47     he = ta = 0;
 48     for(int i = 1;i <= 26;++ i)
 49     {
 50         int tmp = ch[i][0];
 51         if(tmp) q[ta ++] = tmp, fail[tmp] = last[tmp] = 0;
 52     }
 53     while(he < ta)
 54     {
 55         int now = q[he ++];
 56         for(register int i = 1;i <= 26;++ i)
 57         {
 58             int u = ch[i][now];
 59             if(!u)
 60             {
 61                 ch[i][now] = ch[i][fail[now]];
 62                 continue;
 63             }
 64             q[ta ++] = u; 
 65             int v = fail[now];
 66             while(v && !ch[i][v]) v = fail[v];
 67             fail[u] = ch[i][v];
 68             last[u] = tag[fail[u]] ? fail[u] : last[fail[u]];
 69         }
 70     }
 71 }
 72 
 73 //在P中找T的第x行
 74 void find(int u)
 75 {
 76     int j = 0;
 77     for(int i = 1;i <= m;++ i)
 78     {
 79         j = ch[T[u][i] - 'a' + 1][j];
 80         if(tag[j])
 81         {
 82             for(int k = 0;k < node[j].size();++ k)
 83                 if(u - node[j][k] + 1 >= 1) ++ tot[u - node[j][k] + 1][i - y + 1];
 84         }
 85         else if(last[j])
 86         {
 87             for(int k = 0;k < node[last[j]].size();++ k)
 88                 if(u - node[last[j]][k] + 1 >= 1) ++ tot[u - node[last[j]][k] + 1][i - y + 1];
 89         }
 90     }
 91 }
 92 
 93 int main()
 94 {
 95     read(t);
 96     for(;t;--t)
 97     {
 98         for(int i = 1;i <= btot;++ i) node[bq[i]].clear();
 99         btot = 0; cnt = 0, memset(tot, 0, sizeof(tot)), memset(tag, 0, sizeof(tag)), ans = 0, memset(ch, 0, sizeof(ch));
100         read(n), read(m);
101         for(int i = 1;i <= n;++ i)
102             scanf("%s", T[i] + 1);
103         read(x), read(y);
104         for(int i = 1;i <= x;++ i)
105             scanf("%s", P[i] + 1), insert(i);
106         if(n < x || m < y)
107         {
108             printf("0
");
109             continue;
110         }
111         build();
112         for(int i = 1;i <= n;++ i) find(i);
113         for(int i = 1;i <= n - x + 1;++ i) 
114             for(int j = 1;j <= m - y + 1;++ j)
115                 if(tot[i][j] == x) ++ ans;
116         printf("%d
", ans);
117     }
118     return 0;
119 }
UVA11019
原文地址:https://www.cnblogs.com/huibixiaoxing/p/8323528.html