https://codeforces.com/gym/103389/problem/F
实际上比较能看出来是kmp吧。
POJ2185是二维kmp的最小矩阵面积。询问次数多的话就不能每次取字符串遍历了。需要找到一个快速取字符串value的方式就是哈希。
二维的公共前后缀怎么找呢?对每行每列进行哈希的预处理,对于查询的矩阵或者行的哈希值数组。对于列同理。
然后找出行的哈希value的最大公共前后缀长度,即最多可以有多少行。
对列同理找出哈希value的最大公共前后缀长度,即最多可以有多少列。
行数和列数乘积就是答案
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e3+10;
typedef int LL;
typedef unsigned long long ull;
const int base=131;
inline LL read(){
LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){
if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){
x=x*10+ch-48;ch=getchar();}
return x*f;}
ull tr[maxn][maxn],ch[maxn][maxn],a[maxn],p[maxn],d[maxn];
char str[maxn][maxn];
inline int kmppre(int len){
fill(d,d+len+2,0);
int i=1;int j=0;
while(i<len){
if(a[i]==a[j]){
d[i++]=++j;
}else{
if(j) j=d[j-1];
else i++;
}
}
return len-d[len-1];
}
inline int calr(int x1,int y1,int x2,int y2){
for(int i=x1;i<=x2;i++) a[i-x1]=tr[i][y2]-tr[i][y1-1]*p[y2-y1+1];
return kmppre(x2-x1+1);
}
inline int calc(int x1,int y1,int x2,int y2){
for(int i=y1;i<=y2;i++) a[i-y1]=ch[x2][i]-ch[x1-1][i]*p[x2-x1+1];
return kmppre(y2-y1+1);
}
inline void solve(){
int n,q;n=read();q=read();
for(int i=1;i<=n;i++){
scanf("%s",str[i]+1);
}
p[0]=1;
for(int i=1;i<=n;i++){
p[i]=p[i-1]*base;
for(int j=1;j<=n;j++){
tr[i][j]=tr[i][j-1]*base+(str[i][j]-'a');
}
}
for(int j=1;j<=n;j++){
for(int i=1;i<=n;i++)
ch[i][j]=ch[i-1][j]*base+(str[i][j]-'a');
}
while(q--){
int x1,y1,x2,y2;x1=read();y1=read();x2=read();y2=read();
printf("%d\n",calr(x1,y1,x2,y2)*calc(x1,y1,x2,y2));
}
}
int main(void){
solve();
return 0;
}