zoukankan      html  css  js  c++  java
  • UVA

    给你一个n*m的矩阵,和一个x*y的模式矩阵,求模式矩阵在原矩阵中的出现次数。

    看上去是kmp在二维情况下的版本,但单纯的kmp已经无法做到了,所以考虑字符串哈希。

    类比一维情况下的哈希算法,利用容斥可以得到二维情况下的哈希算法,同样可以做到O(1)的查询。总复杂度O(n*m+x*y)。

    蓝书上给的AC自动机的算法复杂度似乎有误,当每行的字符串重复次数过多时复杂度可达O(n*m*x),被hash完爆。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef unsigned long long ll;
     5 const int N=1000+10;
     6 const ll pp1=19260817,pp2=233;
     7 char s[N][N],s2[N][N];
     8 int n,m,n2,m2;
     9 ll h[N][N],h2[N][N],p1[N*N],p2[N*N];
    10 
    11 void gethash(char s[][N],ll h[][N],int n,int m) {
    12     for(int i=0; i<n; ++i)
    13         for(int j=0; j<m; ++j)
    14             h[i+1][j+1]=h[i][j+1]*pp1+h[i+1][j]*pp2-h[i][j]*pp1*pp2+s[i][j];
    15 
    16 }
    17 
    18 ll Hash(ll h[][N],int x1,int y1,int x2,int y2)
    19 {return h[x2+1][y2+1]-h[x1][y2+1]*p1[x2-x1+1]-h[x2+1][y1]*p2[y2-y1+1]+h[x1][y1]*p1[x2-x1+1]*p2[y2-y1+1];}
    20 
    21 int main() {
    22     p1[0]=p2[0]=1;
    23     for(int i=1; i<N*N; ++i)p1[i]=p1[i-1]*pp1,p2[i]=p2[i-1]*pp2;
    24     int T;
    25     scanf("%d",&T);
    26     while(T--) {
    27         scanf("%d%d",&n,&m);
    28         for(int i=0; i<n; ++i)scanf("%s",s[i]);
    29         gethash(s,h,n,m);
    30         scanf("%d%d",&n2,&m2);
    31         for(int i=0; i<n2; ++i)scanf("%s",s2[i]);
    32         gethash(s2,h2,n2,m2);
    33         int ans=0;
    34         for(int i=0; i<n; ++i)if(i+n2-1<n)
    35                 for(int j=0; j<m; ++j)if(j+m2-1<m)
    36                         if(Hash(h,i,j,i+n2-1,j+m2-1)==h2[n2][m2])ans++;
    37         printf("%d
    ",ans);
    38     }
    39     return 0;
    40 }
  • 相关阅读:
    Firebird 用查询结果集更新数据,merge
    wcf 登录认证 angular 认证重定向
    WOSA/XFS PTR Form解析库—xfsptrdata.h
    WOSA/XFS PTR Form解析库—头文件
    2019,开启新征程
    VC中添加头文件以及库
    .net4.0多进程间共享内存实现通信(VB.Net)
    共享内存操作类(C#源码)
    VC++ 共享内存读写操作
    c#实现内存映射文件共享内存
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10340421.html
Copyright © 2011-2022 走看看