#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;
//}
ural1486_二维hash匹配
最新推荐文章于 2019-12-05 18:42:25 发布