zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    AtCoder Grand Contest 033
    Luogu P6620 [省选联考 2020 A 卷] 组合数问题
    Luogu P6631 [ZJOI2020] 序列
    Luogu P6630 [ZJOI2020] 传统艺能
    Luogu P6633 [ZJOI2020] 抽卡
    Luogu P6623 [省选联考 2020 A 卷] 树
    AtCoder Grand Contest 034
    Luogu P5445 [APIO2019] 路灯
    LOJ #6059. 「2017 山东一轮集训 Day1」Sum
    Luogu P3721 [AH2017/HNOI2017]单旋
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8323528.html
Copyright © 2011-2022 走看看