BZOJ1170 Balkan2007 Cipher

这题做的人并不多的样子 , 其实并不是很难啊

提示:

  1. 尝试把矩阵用Hash值表示
  2. 统计一下就好

此题没有详细题解 , 如果有求众数的好方法 , tell me!!

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <map>
#include <algorithm>
#include <cassert>

using namespace std;

typedef unsigned long long ull;

const ull hashNum = 1000007;
const int maxn = 1100;

__inline int re() { int n; scanf("%d" , &n); return n; }

int n , m , x , y;
char g[maxn][maxn];
ull g1[maxn][maxn];
ull Pow[maxn]={1};

map<ull, int> dic;

int main(int argc, char *argv[]) {
    for(int i=1;i<maxn;i++) Pow[i] = Pow[i-1]*hashNum;

    n = re(); m = re();
    for(int i=0;i<=n;i++) gets(g[i]+1);
    x = re(); y = re();

    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) g1[i][j] = g1[i][j-1]*hashNum+g[i][j];
    for(int i=1;i<=n;i++) for(int j=m;j>=y;j--) g1[i][j] -= g1[i][j-y]*Pow[y];
    for(int i=1;i<=n;i++) for(int j=y;j<=m;j++) g1[i][j] += g1[i-1][j]*hashNum;
    for(int i=n;i>=x;i--) for(int j=y;j<=m;j++) g1[i][j] -= g1[i-x][j]*Pow[x];

    for(int i=x;i<=n;i++) for(int j=y;j<=m;j++) dic[g1[i][j]]++;

    int Max = 0; ull who;
    for(map<ull , int>::iterator i = dic.begin();i!=dic.end();i++) 
        if(Max < i->second) Max = i->second , who = i->first;

// int X = 4 , Y = 3;
// cout<<g1[X+x-1][Y+y-1]<<endl;
    printf("%d %d\n" , x , y);
    bool first = true;
    assert(Max<=1000);
    for(int i=x;i<=n;i++) for(int j=y;j<=m;j++) if(who == g1[i][j])
    {
        if(first)
        {
            first = false;
            for(int ii=i-x+1;ii<=i;ii++) 
            { for(int jj=j-y+1;jj<=j;jj++) printf("%c" , g[ii][jj]); puts(""); }
            printf("%d\n" , Max);
        }

        printf("%d %d\n" , i-x+1 , j-y+1);
    }

    return 0;
}

你可能感兴趣的:(hash)