zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Java 实现 HDFS 文件基本操作
    [git] branch 分支操作
    Java基本语法-----java流程控制语句
    Java基本语法-----java运算符的优先级与结合性
    Java基本语法-----java数据类型的转换
    CSDN发表文章后老是待审核的原因
    Java基本语法-----java变量
    Java基本语法-----java进制的转换
    Java基本语法-----java常量
    Java基本语法-----java注释
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8640803.html
Copyright © 2011-2022 走看看