UVALive

来源:互联网 发布:php集成环境搭建 编辑:程序博客网 时间:2024/06/06 00:15

传送门:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4905

题意大意:

给出一个模式字符矩阵,然后再给出一个匹配字符矩阵,问模式字符矩阵在匹配字符矩阵中出现的次数。可以看样例,那更加直观。

题解:

既然是字符匹配,那么首先想到是关于字符处理的一些知识,比如KMP,AC自动机,后缀树组等等。但是这些都不会!!!!至于KMP没应用到过二维的。前段时间学习了BKDRhash字符串哈希。当时练习的是求解一维匹配的。现在要将它转化到二维。其实思路很简单。如果读者还不了解BKDRhash,那就先了解一下BKDRhash。然后将每一列或者每一行对其hash,这里用的对每一列。把一列当成一维字符串进行哈希。如下图:



如上图假设匹配的是红色区域内的字符矩阵,那么对于第一列来讲(将每一列看成一维的字符串哈希处理)它的哈希值就是col1='a'*seed^2+'b'*seed^1+'c'*seed^0,(seed是其系数基值)第二列就是col2='d'*seed^2+'e'*seed^1+'f'*seed^0,第三列col3='g'*seed^2+'h'*seed^1+'k'*seed^0;那么现在应该把这个矩阵合并成一个哈希值。现在把这个字符矩阵平铺开得:‘a ’ ‘b ’ ‘c ’ ‘d ’ ‘e ’ ‘f ’ ‘g ’ ‘h ’ ‘k’,如果把它看成一维的话的哈希值是多少呢:'a'*seed^8+'b'*seed^7+'c'*seed^6+'d'*seed^5+'e'*seed^4+'f'*seed^3+'g'*seed^2+'h'*seed^1+'k'*seed^0;那么看看这个哈希值怎么由col1,col2,col3得来呢。很容易看出是col1*seed^6+col2*seed^3+col3*seed^0,也就是现在的基值是base[3]即base[row],row是模式串的行。剩下的就看看代码吧。注意行列在处理的时候有些变化。因为是按着列来哈希的,但输入是一行一行输入的。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>#include <cmath>using namespace std;const int MAXN = 2000+100;typedef unsigned long long LL;int n1,m1,n2,m2;LL base[MAXN*MAXN+100];const int seed = 31;char s1[MAXN][MAXN],s2[MAXN][MAXN];LL val,H[MAXN][MAXN];void init(){    base[0]=1;    for(int i=1;i<=MAXN*MAXN;i++)        base[i]=base[i-1]*seed;}void get_H(){    val=0;    for(int i=1;i<=n1;i++)        for(int j=1;j<=m1;j++)        val=val*seed+s1[i][j]-'a'+1;    memset(H,0,sizeof(H));    for(int i=1;i<=n2;i++)    {        for(int j=1;j<=m2;j++)        {            H[i][j]=H[i][j-1]*seed+(s2[i][j]-'a'+1);        }    }}void work(){    int ans=0;   for(int i=1;i<=m2-m1+1;i++)   {       int li=i-1,ri=i+m1-1;       LL temp=0;       int j;       for(j=1;j<=n1;j++)       temp=temp*base[m1]+H[j][ri]-H[j][li]*base[m1];       do       {           if(val==temp)           {                //cout<<li<<" "<<ri<<" "<<j<<endl;               ans++;           }           temp-=(H[j-n1][ri]-H[j-n1][li]*base[m1])*base[(n1-1)*m1];           temp=temp*base[m1]+H[j][ri]-H[j][li]*base[m1];           j++;       }while(j<=n2+1);   }   printf("%d\n",ans);}int main(){    init();    while(scanf("%d%d%d%d",&n1,&m1,&n2,&m2)==4&&n1)    {        for(int i=1;i<=n1;i++)            scanf("%s",s1[i]+1);        for(int i=1;i<=n2;i++)            scanf("%s",s2[i]+1);        get_H();        work();    }    return 0;}


原创粉丝点击