JZOJ4683 矩阵

来源:互联网 发布:海隆软件 编辑:程序博客网 时间:2024/05/02 02:32

题目大意

给一个n*m的字符矩阵,求有多少个不同的子矩阵,字符集为大写英文字母。
n,m<=110

分析

先往哈希上面想想,直接暴力搞每一个矩阵的哈希值再判重是n6,然后就开始优化。首先确定宽度,行数就可以递增地继承信息。而宽度的递增,也是可以继承的,最后就可以n4
实际上,我们确定宽度width以后,就可以转化为新矩阵,其中每一个元素都是原矩阵1*width的子矩阵。这样我们只用统计整个矩阵里,k*1的不同子矩阵个数。把它们打横来看,就是数个字符串了。用特殊字符#把数个字符串连接起来,问题变成求整个字符串里,不包含#的不同子串有多少个。
SA或者SAM解决了。

写题

智商捉急啊···一开始用特殊的哈希技巧来打70分,结果哈希太烂,小数据都会有误。
改题的时候,SA好久不打了,还得看模板,所以改题效率特别低。正确的姿势是回忆好SA,再开始打。然而我边打边看,不能专一做事,脑子一片混乱,调试也不高效。这是值得注意的地方。
还有一点,字符串哈希最好用多个质数模数。

贴个代码

#include<cstdio>#include<algorithm>using namespace std;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)typedef long long ll;const int N=115,N2=24205,mo=1000000007,mo1=128473;char ch;int f[N][N],g[N][N],sa[N2],height[N2],x[N2],x1[N2],y[N2],wv[N2],ws[N2],n,m,i,j,k,l,a[N][N],res,rank[N2],tt,t1,p,pos,dur,ans,width;struct rec{    int val,pos,val1;}b[N2];bool cmp(rec a,rec b){    return a.val<b.val;}void getsa(){    fo(i,1,tt) wv[i]=0;    fo(i,1,tt) wv[x[i]]++;    fo(i,1,tt) wv[i]+=wv[i-1];    fd(i,tt,1)    {        sa[wv[x[i]]]=i;        wv[x[i]]--;    }    j=1;    while (j<=tt)    {        p=0;        fo(i,tt-j+1,tt) y[++p]=i;        fo(i,1,tt)            if (sa[i]>j)                y[++p]=sa[i]-j;        fo(i,1,tt) wv[i]=0;        fo(i,1,tt) ws[i]=x[y[i]];        fo(i,1,tt) wv[ws[i]]++;        fo(i,1,tt) wv[i]+=wv[i-1];        fd(i,tt,1)        {            sa[wv[ws[i]]]=y[i];            wv[ws[i]]--;        }        p=1;        fo(i,1,tt) y[i]=x[i];        x[sa[1]]=1;        fo(i,2,tt)        {            if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j])                p++;            x[sa[i]]=p;        }        j*=2;    }}void getheight(){    fo(i,1,tt) rank[sa[i]]=i;    k=0;    fo(i,1,tt)    {        if (k) k--;        j=sa[rank[i]-1];        while (j+k<=tt&&i+k<=tt&&x1[j+k]==x1[i+k]) k++;        height[rank[i]]=k;    }}void getans(){    fo(i,1,tt)    {        pos=sa[i];        dur=((sa[i]-1)/(n+1)+1)*(n+1)-pos;        ans+=max(dur-height[i],0);    }}int main(){    freopen("matrix.in","r",stdin);//  freopen("matrix.out","w",stdout);    scanf("%d%d\n",&n,&m);    fo(i,1,n)    {        fo(j,1,m)        {            scanf("%c",&ch);            a[i][j]=ch;        }        scanf("\n");    }    fo(width,1,m)    {        tt=0;        res=m-width+1;        fo(i,1,n) fo(j,1,res)         {            g[i][j]=0;            f[i][j]=(ll)(f[i][j]*13531+a[i][j+width-1])%mo;            b[++tt].val=f[i][j];            b[tt].pos=i*m+j-1;        }        sort(b+1,b+1+tt,cmp);        b[0].val=-1;        t1=0;        fo(i,1,tt)        {            if (b[i].val!=b[i-1].val) t1++;            g[b[i].pos/m][b[i].pos%m+1]=t1;        }        tt=0;        fo(j,1,res)        {            fo(i,1,n)                x[++tt]=g[i][j];            x[++tt]=t1+1;        }        fo(i,1,tt) x1[i]=x[i];        getsa();        getheight();        getans();        fo(i,1,tt+4) y[i]=wv[i]=ws[i]=sa[i]=rank[i]=height[i]=x[i]=x1[i]=0;    }    printf("%d",ans);}
0 0