ural1486_二维hash匹配

#include<iostream>
#include<map>
#include<string>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<stack>
#include<vector>
#include<ctime>
#include<set> 
#include<cctype>
#include<cstdlib>
using namespace std;
const double eps=1e-7;
const int K=1024;
const int maxn= 502;
const int maxh=maxn*maxn;
const int INF = (1<<30);
typedef unsigned long long ULL;
//#define debug
const int P=975637;
const int Q=773331;
const int P2=977717;
const int Q2=773371;
int n,m,tot,ans_L;
char G[maxn][maxn];
int R,R2,p1[maxn],p2[maxn],p3[maxn],p4[maxn],hs_r[maxn][maxn],hs2_r[maxn][maxn],hs_t[maxn][maxn],hs2_t[maxn][maxn],hs_f[maxh];
pair<int,int> ans[2],vec[maxh][2];
void init(){
	p1[1]=p2[1]=1;
	p3[1]=p4[1]=1;
	for(int i = 2; i <= m; ++i) {
		p1[i]=((ULL)p1[i-1]*26)%Q;
		p3[i]=((ULL)p3[i-1]*26)%Q2;
	}
	R=((ULL)p1[m]*26)%Q;
	R2=((ULL)p3[m]*26)%Q2;
	for(int i = 2; i <= n; ++i) {
		p2[i]=((ULL)p2[i-1]*R)%P; 
		p4[i]=((ULL)p4[i-1]*R2)%P2;
	}
}
bool ts(int len){
	for(int i = 1;i <= n; ++i){
		hs_r[i][1]=0;
		hs2_r[i][1]=0;
		for(int j = 1;j <= len; ++j){
			hs_r[i][1]=((ULL)hs_r[i][1]*26+G[i][j])%Q;
			hs2_r[i][1]=((ULL)hs2_r[i][1]*26+G[i][j])%Q2;
		}
		for(int j = 2;j <= m-len+1; ++j){
			hs_r[i][j]=((26*(Q+hs_r[i][j-1]-((ULL)p1[len]*G[i][j-1])%Q)%Q)%Q+G[i][j+len-1])%Q; 
			hs2_r[i][j]=((26*(Q2+hs2_r[i][j-1]-((ULL)p3[len]*G[i][j-1])%Q2)%Q2)%Q2+G[i][j+len-1])%Q2; 
		}
	}
	for(int j = 1; j <=m-len+1; ++j){
		hs_t[1][j]=0;
		hs2_t[1][j]=0;
		for(int i = 1; i <= len; ++i){
			hs_t[1][j]=((ULL)hs_t[1][j]*R + hs_r[i][j])%P;
			hs2_t[1][j]=((ULL)hs2_t[1][j]*R2 + hs2_r[i][j])%P2;
		}
		for(int i = 2; i <= n-len+1;++i){
			hs_t[i][j]=((R*(P+hs_t[i-1][j]-((ULL)hs_r[i-1][j]*p2[len])%P)%P)%P+hs_r[i+len-1][j])%P;
			hs2_t[i][j]=((R2*(P2+hs2_t[i-1][j]-((ULL)hs2_r[i-1][j]*p4[len])%P2)%P2)%P2+hs2_r[i+len-1][j])%P2;
		}
	}
	memset(hs_f,0,sizeof(hs_f));
	tot=0;
	for(int i = 1;i <= n-len+1; ++i){
		for(int j = 1; j <= m-len+1; ++j){
			int u=hs_t[i][j],v=hs2_t[i][j];
			int h=((ULL)u*v) % maxh;
			if(u>v) swap(u,v);
			while(hs_f[h]){
				if(vec[hs_f[h]][0].first==u&&vec[hs_f[h]][0].second==v){
					bool flag=true;
					int ii=vec[hs_f[h]][1].first,jj=vec[hs_f[h]][1].second;
					for(int x = 0; flag&&x < len; ++x){
						for(int y = 0; y < len; ++y){
							if(G[x+i][y+j]!=G[x+ii][y+jj]){flag=false;break;}
						}
					}
					if(flag){
						if(ans_L < len){
							ans_L=len;
							ans[0].first=ii;
							ans[0].second=jj;
							ans[1].first=i;
							ans[1].second=j;
						}
						return true;
					}
				}
				++h;
				if(h==maxh) h=0;
			}
			hs_f[h]=++tot;
			vec[tot][0].first=u;
			vec[tot][0].second=v;
			vec[tot][1].first=i;
			vec[tot][1].second=j;
		}
	}
	return false;
}
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; ++i){
		scanf("%s",&G[i][1]);
		for(int j = 1; j <= m; ++j) G[i][j]-='a';
	}
	init();
	int left=1,right=min(n,m);
	while(left<=right){
		int mid=(left+right)>>1;
		if(ts(mid)) left=mid+1;
		else right=mid-1;
	}
	if(ans_L>0){
		printf("%d\n",ans_L);
		printf("%d %d\n",ans[0].first,ans[0].second);
		printf("%d %d\n",ans[1].first,ans[1].second);
	}else puts("0");
	return 0;
}


//#include<iostream>
//#include<map>
//#include<string>
//#include<algorithm>
//#include<bitset>
//#include<cassert>
//#include<cstring>
//#include<cmath>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<vector>
//#include<ctime>
//#include<set> 
//#include<cctype>
//#include<cstdlib>
//using namespace std;
//const double eps=1e-7;
//const int K=1024;
//const int maxn= 510;
//const int INF = (1<<30);
//typedef unsigned long long ULL;
//#define debug
//const int P=95565617;
//const int Q=3333371;
//const int P2=75565617;
//const int Q2=3133371;
//int n,m,pn,ans_L;
//char G[maxn][maxn];
//int R,p1[maxn],p2[maxn],hs_r[maxn][maxn],hs_t[maxn][maxn];
//multimap<int,pair<int,int> > cf;
//typedef multimap<int,pair<int,int> >::iterator cfit;
//pair<int,int> ans[2],ans2;
//bool cmp(int h,int w,int len){
//	 cfit itlow=cf.lower_bound(hs_t[h][w]);
//	 cfit itup =cf.upper_bound(hs_t[h][w]);
//	 for(cfit it=itlow; it != itup; ++it){
// 		ans2=it->second;
//		bool flag=true;
//		for(int i = 0; flag&&i < len; ++i){
//			for(int j = 0; j < len; ++j){
//				if(G[i+h][j+w]!=G[i+ans2.first][j+ans2.second]){
//					flag=false;
//					break;
//				}
//			}
//		}
//		if(flag){
//			if(ans_L < len){
//				ans_L=len;
//				ans[0]=ans2;
//				ans[1].first=h;
//				ans[1].second=w;
//				if(ans[0]>ans[1]) swap(ans[0],ans[1]);
//			}
//			return true;
//		}
//	 }
//	 return false;
//}
//bool ts(int len){
//	for(int i = 1;i <= n; ++i){
//		hs_r[i][1]=0;
//		//hs2_r[i][1]=0;
//		for(int j = 1;j <= len; ++j){
//			hs_r[i][1]=((ULL)hs_r[i][1]*26+G[i][j])%Q;
//			//hs2_r[i][1]=(hs2_r[i][1]*26+G[i][j])%Q2;
//		}
//		for(int j = 2;j <= m-len+1; ++j){
//			hs_r[i][j]=(
//				(26*(Q+hs_r[i][j-1]-((ULL)p1[len]*G[i][j-1])%Q)%Q)%Q
//				+G[i][j+len-1]
//			)%Q; 
//			/*hs2_r[i][j]=(
//				(26*(Q2+hs2_r[i][j-1]-(p3[len]*G[i][j-1])%Q2)%Q2)%Q2
//				+G[i][j+len-1]
//			)%Q2;*/
//		}
//	}
//	for(int j = 1; j <=m-len+1; ++j){
//		hs_t[1][j]=0;
//		//hs2_t[1][j]=0;
//		for(int i = 1; i <= len; ++i){
//			hs_t[1][j]=((ULL)hs_t[1][j]*R + hs_r[i][j])%P;
//			//hs2_t[1][j]=(hs2_t[1][j]*R2 + hs2_r[i][j])%P2;
//		}
//		for(int i = 2; i <= n-len+1;++i){
//			hs_t[i][j]=(
//				((ULL)R*((ULL)P+hs_t[i-1][j]-((ULL)hs_r[i-1][j]*p2[len])%P)%P)%P
//				+hs_r[i+len-1][j]
//			)%P;
//		/*	hs2_t[i][j]=(
//				(R2*(P2+hs2_t[i-1][j]-(hs2_r[i-1][j]*p4[len])%P2)%P2)%P2
//				+hs2_r[i+len-1][j]
//			)%P2;*/
//		}
//	}
//#ifdef debug
//	printf("len:%d\n",len);
//	printf("%d %d\n",hs_r[1][1],hs_r[3][3]);
//	printf("%d %d\n",hs_t[1][1],hs_t[3][3]);
//#endif
//	cf.clear();
//	for(int i = 1;i <= n-len+1; ++i){
//		for(int j = 1; j <= m-len+1; ++j){
//			pair<int,int> t(i,j);
//			if(cmp(i,j,len)){
//				return true;
//			}
//			cf.insert(make_pair(hs_t[i][j],t));
//		}
//	}
//	return false;
//}
//int main(){
//	freopen("in.txt","r",stdin);
//	scanf("%d%d",&n,&m);
//	for(int i = 1; i <= n; ++i){
//		scanf("%s",&G[i][1]);
//		for(int j = 1; j <= m; ++j) G[i][j]-='a';
//	}
//	//no.1 hash
//	p1[1]=p2[1]=(ULL)1;
//	for(int i = 2; i <= m; ++i) p1[i]=(p1[i-1]*26)%Q;
//	R=(p1[m]*26)%Q;
//	for(int i = 2; i <= n; ++i) p2[i]=(p2[i-1]*R)%P;
//	//no.2 hash
//	/*p3[1]=p4[1]=(ULL)1;
//	for(int i = 2; i <= m; ++i) p3[i]=(p3[i-1]*26)%Q2;
//	R2=(p3[m]*26)%Q2;
//	for(int i = 2; i <= n; ++i) p4[i]=(p4[i-1]*R2)%P2;*/
//
//    int left=1,right=min(n,m);
//	while(left<=right){
//		int mid=(left+right)>>1;
//		if(ts(mid)) left=mid+1;
//		else right=mid-1;
//	}
//	if(ans_L>0){
//		printf("%d\n",ans_L);
//		printf("%d %d\n",ans[0].first,ans[0].second);
//		printf("%d %d\n",ans[1].first,ans[1].second);
//	}else puts("0");
//	return 0;
//}

编码请看:http://www.maidoupig.cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值