F. 地图压缩(二维kmp+哈希)

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/121231698