URAL

来源:互联网 发布:下载识谱软件 编辑:程序博客网 时间:2024/05/17 00:15

Equal Squares

 URAL - 1486


During a discussion of problems at the Petrozavodsk Training Camp, Vova and Sasha argued about who of them could in 300 minutes find a pair of equal squares of the maximal size in a matrix of size N ×  M containing lowercase English letters. Squares could overlap each other but could not coincide. He who had found a pair of greater size won. Petr walked by, looked at the matrix, said that the optimal pair of squares had sides K, and walked on. Vova and Sasha still cannot find this pair. Can you help them?
Input
The first line contains integers N and M separated with a space. 1 ≤  NM ≤ 500. In the next N lines there is a matrix consisting of lowercase English letters, M symbols per line.
Output
In the first line, output the integer K which Petr said. In the next two lines, give coordinates of upper left corners of maximal equal squares. If there exist more than one pair of equal squares of size K, than you may output any of them. The upper left cell of the matrix has coordinates (1, 1), and the lower right cell has coordinates ( N,  M). If there are no equal squares in the matrix, then output 0.
Example
inputoutput
5 10ljkfghdfasisdfjksiyepgljkijlgpeyisdafdsilnpglkfkjl
31 13 3

Source
URAL - 1486
My Solution
题意:给出n个长度为m的字符串(n,m <= 500),然后问选取一个最大的正方形,使得有2个正方形区域的字符串是相同的,求出这个最大正方形的边长即两次出现位置的正方形左上角坐标。
哈希、二维hash、二分、卡大素数
题目直接就暗示着用哈希来做 ^_^,
然后可以把每个字符串分别用同一个大素数hash掉,
然后二分边长,
check的时候,检查每个长度为mid的正方形是否再次出现,
检查的时候再去另一个大素数pt,把横向的第一次哈希得到的一段字符串的哈希值作为一个元素,把这些元素再次进行哈希,
然后在纵向的求长度为mid的,哈希值是否再次出现。
然后卡大素数了,所以把1e12+9改成了 191919191919。
复杂度 O(n*n*logn)
#include <iostream>#include <cstdio>#include <string>#include <map>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;typedef pair<int, int> ii;typedef unsigned long long ull;const int MAXN = 5e2 + 8;const ull p = 1e12 + 7, pt = 191919191919;struct ha{    ull ha[MAXN][MAXN], xp[MAXN], sz;    void init1(int n){        sz = n;        xp[0] = 1;        for(int i = 1; i <= sz; i++) xp[i] = xp[i-1] * p;    }    void init2(int id, const string &str){//0~n-1 based        ha[id][sz] = 0;        for(int i = sz - 1; i >= 0; i--){            ha[id][i] = ha[id][i+1] * p + (str[i] - 'a' + 1);        }    }    ull get_ha(int id, int st, int len){        return ha[id][st] - ha[id][st + len] * xp[len];    }}Hash;string s[MAXN];map<ull, ii> mp;int n, m, ansk = 0;ii ans1, ans2;ull hat[MAXN], xpt[MAXN];inline void initxpt(int sz){    xpt[0] = 1;    for(int i = 1; i <= sz; i++) xpt[i] = xpt[i-1] * pt;}inline bool check(int x){    mp.clear();    int i, j, k;    ull t;    for(j = 0; j + x - 1 < m; j++){        hat[0] = 0;        for(i = 1; i <= n; i++){            hat[i] = hat[i-1]*pt + Hash.get_ha(i, j, x);        }        for(k = x; k <= n; k++){            t = hat[k] - hat[k - x] * xpt[x];            if(mp.find(t) != mp.end()){                ans1 = mp[t];                ans2 = ii(k - x + 1, j + 1);                return true;            }            else{                mp[t] = ii(k - x + 1, j + 1);            }        }    }    return false;}int main(){    #ifdef LOCAL    freopen("17.in", "r", stdin);    //freopen("17.out", "w", stdout);    #endif // LOCAL    ios::sync_with_stdio(false); cin.tie(0);    cin >> n >> m;    Hash.init1(m);    for(int i = 1; i <= n; i++){        cin >> s[i];        Hash.init2(i, s[i]);    }    initxpt(n);    int l = 0, r = min(n, m) + 1, mid;    while(l + 1 < r){        mid = (l + r) >> 1;        if(check(mid)){            ansk = mid; l = mid;        }        else r = mid;    }    if(ansk) cout << ansk << "\n" << ans1.first << " " << ans1.second << "\n" << ans2.first << " " << ans2.second << endl;    else cout << ansk << "\n";    return 0;}

Thank you!
                                                                                                                                             ------from ProLights

0 0