• UVa 11019 Matrix Matcher


    题目传送门

      快速的vjudge传送门

      快速的UVa传送门

    题目大意

      给定两个矩阵S和T,问T在S中出现了多少次。

      不会AC自动机做法。

      考虑一维的字符串Hash怎么做。

      对于一个长度为$l$的字符串$s$,它的Hash值$hash(s) = sum_{i = 1}^{l}x^{l - i}s_{i}$。

      对于二维的情况,我们就取两个基,$x, y$,对于一个$n imes m$的矩阵$A$的Hash值可以表示为

    $hash(A) = sum_{i = 1}^{n}sum_{j = 1}^{m}x^{n - i}y^{m - j}a_{ij}$

      然后以记录$S$的左上角的左上角的所有子矩阵的hash值(这个可以$O(1)$转移)。询问一个子矩阵的hash值,就可以$O(1)$回答。

      接下来就很简单了。枚举每个位置判断是否匹配。

    Code

     1 /**
     2  * UVa
     3  * Problem#11019
     4  * Accepted
     5  * Time: 50ms
     6  */
     7 #include <iostream>
     8 #include <cstdlib>
     9 #include <cstdio>
    10 using namespace std;
    11 typedef bool boolean;
    12 
    13 const unsigned int hash1 = 200379, hash2 = 211985;
    14 const int N = 1005, M = 105;
    15 
    16 int p1[N], p2[N];
    17 int m, n, x, y;
    18 char S[N][N], T[M][M];
    19 unsigned int hs[N][N];
    20 
    21 inline void prepare() {
    22     p1[0] = 1, p2[0] = 1;
    23     for (int i = 1; i < N; i++)
    24         p1[i] = p1[i - 1] * hash1;
    25     for (int i = 1; i < N; i++)
    26         p2[i] = p2[i - 1] * hash2;
    27 }
    28 
    29 inline void init() {
    30     scanf("%d%d", &n, &m);
    31     for (int i = 1; i <= n; i++)
    32         scanf("%s", S[i] + 1);
    33     scanf("%d%d", &x, &y);
    34     for (int i = 1; i <= x; i++)
    35         scanf("%s", T[i] + 1);
    36 }
    37 
    38 inline void solve() {
    39     for (int i = 1; i <= n; i++)
    40         for (int j = 1; j <= m; j++) {
    41             hs[i][j] = hs[i - 1][j - 1] * hash1 * hash2 + (hs[i - 1][j] - hs[i - 1][j - 1] * hash2) * hash1 + (hs[i][j - 1] - hs[i - 1][j - 1] * hash1) * hash2 + S[i][j];
    42         }
    43     
    44 /*    unsigned int s1 = 0;
    45     for (int i = 1; i <= n; i++)
    46         for (int j = 1; j <= m; j++)
    47             s1 += S[i][j] * p1[n - i] * p2[m - j];
    48     
    49     cerr << s1 << " " << (97u * 200379 * 211985 + 98u * 200379 + 98u * 211985 + 97) << " " << hs[2][2] << endl;*/
    50     
    51     int rt = 0;
    52     unsigned int s = 0, c;
    53     for (int i = 1; i <= x; i++)
    54         for (int j = 1; j <= y; j++)
    55             s += T[i][j] * p1[x - i] * p2[y - j];
    56 //    cerr << s << endl;
    57     for (int i = x; i <= n; i++)
    58         for (int j = y; j <= m; j++) {
    59             c = hs[i][j] - hs[i - x][j - y] * p1[x] * p2[y] - (hs[i][j - y] - hs[i - x][j - y] * p1[x]) * p2[y] - (hs[i - x][j] - hs[i - x][j - y] * p2[y]) * p1[x];
    60             if (s == c)
    61                 rt++;       
    62         }
    63     printf("%d
    ", rt);
    64 }
    65 
    66 int kase;
    67 int main() {
    68     prepare();
    69     scanf("%d", &kase);
    70     while (kase--) {
    71         init();
    72         solve();
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    微信助力活动表结构设计
    mysql的in查询分析
    PHP从数组中找到指定元素的位置
    Java程序使用Alpine Linux报错java.lang.NoClassDefFoundError: Could not initialize class org.xerial.snappy.Snappy解决
    Eclipse/Idea 代码格式化部分忽略
    修改Linux桌面高分屏下QT程序界面的缩放
    折腾linux随笔 之 关闭Budgie默认自动隐藏应用的菜单栏 与 Gnome系桌面应用菜单无内容解决
    Debian Buster 使用Lxde在界面中打开url提示错误解决
    Portainer容器可视化管理工具使用文档
    Lxde添加触摸板双击功能、防误触
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8640803.html
Copyright © 2020-2023  润新知