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;}
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- SCTP
- x264中的汇编:DCT变换 dct-a.asm——004
- 11.Service的使用
- 【CodeForces】616D
- JS数字精度丢失详解
- UVALive
- 列表解析(推导)
- 各种对话框的实现(文字对话框,选择对话框,弹出输入对话框,单选,多选对话框,自定义对话框)
- hadoop安装时容易出现的错误
- HEVC中需要汇编优化的关键耗时函数——005
- 我对Java+Oracle数据库编程(JDBC)的理解与核心内容分析
- 一些基本的调试技巧--C语言(二)
- 002 Python前端之CSS基础
- 一个关于invalidateOptionsMenu方法的小问题