Ural 1486. Equal Squares 字符串hash

来源:互联网 发布:免费linux服务器 编辑:程序博客网 时间:2024/05/08 11:39

1486. Equal Squares

Time limit: 2.0 second
Memory limit: 16 MB
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 sizeN × 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 Nlines 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 (NM). If there are no equal squares in the matrix, then output 0.

Sample

inputoutput
5 10ljkfghdfasisdfjksiyepgljkijlgpeyisdafdsilnpglkfkjl
31 13 3
Problem Author: Vladimir Yakovlev
Problem Source: The XIth USU Programing Championship, October 7, 2006
题意:一个n*m的矩阵,求此矩阵中最大的完全相同的2个正方形。
论文例题:《Hash在信息学竞赛中的一类应用http://www.doc88.com/p-167100142515.html
二分查找正方形的边长,然后使用一个Hash表来判断该边长是否可行。

多维的KMP要从1维的情况开始考虑,并推广至高维。那么这种计算Hash函数的匹配算法我们也可以先考虑一维的情况——就是Rabin-Karp算法。

对于一个字符串S,可以使用这个函数求出其Hash值:


那么,模式串Y的Hash值就可以轻松地求出。记待匹配串X从第i个字符开始的长度为M的子串为Si,则不难发现f(Si+1)和f(Si)的关系:


换个角度,如果不考虑mod q,这个函数就是把字符串看作一个p进制数求出的值,这样,Xi+1就是Xi “左移”一位,然后去掉最前面一位,再加上右面新进来的一位得到的。因此上面的递推公式也是显然的。

#include<stdio.h>#include<cstring>#include<cstdlib>#define Min(a,b) (a<b?a:b)struct node{    int x,y;} hash[250008],a1,a2;int  p=4877;int n,m,f[505][505],ans,x1,x2,y1,y2,a[505][505],g[505][505],b[250008],next[250008],start[530000],tot;long long s[505];void  insert(int x,node t)//将HASH值x插入链表{    hash[++tot]=t;    next[tot]=start[x];    start[x]=tot;}bool  cmp(int x,int l)//比较HASH值为X的相同矩阵是否出现过{    int i,j;    for  (int g=start[x]; g; g=next[g])    {        a2=hash[g];        j=l;        for  (i=0; i<l&&j>=l; i++)            if  (f[a1.x][a1.y-i]!=f[a2.x][a2.y-i]) break;        if  (i>=l)        {            if  (l>ans) ans=l,x1=a1.x,y1=a1.y,x2=a2.x,y2=a2.y;            return true;        }    }    return false;}int  main(){    int i,j,k,l,r;    char c;    scanf("%d%d%*c",&n,&m);    for  (i=1; i<=n; i++)    {        for  (j=1; j<=m; j++)        {            scanf("%c",&a[i][j]);            a[i][j]-=97;        }        scanf("%*c");    }    s[0]=1;    for  (i=1; i<=n; i++) s[i]=(p*s[i-1])&524287;    r=Min(n,m);    l=1;    while  (l<=r)    {        k=l+r>>1;        for  (i=1; i<=n; i++)            for  (j=1; j<=m; j++)            {                if  (i<k) f[i][j]=f[i-1][j]*p+a[i][j]&524287;                else  f[i][j]=((f[i-1][j]-a[i-k][j]*s[k-1]&524287)+524288&524287)*p+a[i][j]&524287;//减去最高位,加上最低位            }//f[i][j]存下第j列第i行往上长度为k的串的HASH值        memset(start,0,sizeof(start));        tot=0;        for  (j=1; j<=m&&i>n; j++)            for  (i=k; i<=n; i++)            {                if  (j<k) g[i][j]=g[i][j-1]*p+f[i][j]&524287;                else                {                    g[i][j]=((g[i][j-1]-f[i][j-k]*s[k-1]&524287)+524288&524287)*p+f[i][j]&524287;                    if  (cmp(g[a1.x=i][a1.y=j],k))   break;                    insert(g[i][j],a1);                }            }//g[i][j]存下右下角为第i行第j列长度为k的矩阵的HASH值        if  (j<=m) l=k+1;        else r=k-1;    }    if  (ans)  printf("%d\n%d %d\n%d %d\n",ans,x1-ans+1,y1-ans+1,x2-ans+1,y2-ans+1);    else  printf("0\n");    return 0;}



原创粉丝点击