http://poj.org/problem?id=3690
UVA还有一道也是这样的题,LRJ给的算法是AC自动机----我还没写过,今天用HASH搞了这道题
思路很清晰,但是处理起来还因为HASH函数写混WA了几次。。。
文本矩阵n*m T个匹配矩阵p*q
思路:
1、把每一行处理出长为q的hash值
2、对于1中得到的p个哈希值在算一次哈希,这样就把一个矩阵用一个hash值替代了
3、把所有的匹配矩阵压入multiset,然后对于文本矩阵的每一个p*q的子矩阵,算出矩阵哈希值,从multiset中删去该值
4、ans=T-multiset.size()
本题可以作为字符矩阵匹配模板
#include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdin) const ull ba1=9973; const ull ba2=1e8+7; const int MAXT=1000+10; const int MAXP=MAXT;//55; char text[MAXT][MAXT]; char pat[100+5][MAXP][MAXP]; ull ha[MAXT][MAXT],tmp[MAXT][MAXT]; ull base1[MAXT],base2[MAXT]; int N,M,T,P,Q; void init() { base1[0]=1; base2[0]=1; for(int i=1;i<MAXT;i++) { base1[i]=base1[i-1]*ba1; base2[i]=base2[i-1]*ba2; } } void calhash(char mat[][MAXT],int n, int m) { ull e; //行 for(int i=0;i<n;i++) { for(int j=0;j<Q;j++) tmp[i][j]=(j==0)?mat[i][j]:(tmp[i][j-1]*ba1+mat[i][j]); for(int j=Q;j<m;j++) tmp[i][j]=tmp[i][j-1]*ba1+mat[i][j]-mat[i][j-Q]*base1[Q]; } //列 for(int j=Q-1;j<m;j++) { for(int i=0;i<P;i++) ha[i][j]=(i==0)?tmp[i][j]:(ha[i-1][j]*ba2+tmp[i][j]); for(int i=P;i<n;i++) ha[i][j]=ha[i-1][j]*ba2+tmp[i][j]-tmp[i-P][j]*base2[P]; } } int solve() { multiset<ull>app; for(int i=0;i<T;i++) { calhash(pat[i],P,Q); app.insert(ha[P-1][Q-1]); /*printf("#T--%d# ",i); for(int i=0;i<P;i++) { for(int j=0;j<Q;j++) cout << tmp[i][j] << "/" << ha[i][j] << " "; putchar('\n'); }*/ } calhash(text,N,M); for(int i=P-1;i<N;i++) for(int j=Q-1;j<M;j++) app.erase(ha[i][j]); return T-app.size(); } int main() { //IN("poj3690.txt"); init(); int ic=0,ans; while(~scanf("%d%d%d%d%d",&N,&M,&T,&P,&Q) && N+M+T+P+Q) { for(int i=0;i<N;i++) scanf("%s",text[i]); for(int i=0;i<T;i++) { for(int j=0;j<P;j++) scanf("%s",pat[i][j]); } printf("Case %d: %d\n",++ic,solve()); } return 0; }
poj 3690 字符矩阵匹配----HASH算法
时间: 2024-11-13 21:00:15