JZOJ4683 矩阵
来源:互联网 发布:海隆软件 编辑:程序博客网 时间:2024/05/02 02:32
题目大意
给一个n*m的字符矩阵,求有多少个不同的子矩阵,字符集为大写英文字母。
n,m<=110
分析
先往哈希上面想想,直接暴力搞每一个矩阵的哈希值再判重是
实际上,我们确定宽度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
- JZOJ4683 矩阵
- [HDU4029]Distinct Sub-matrix/[JZOJ4683]矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 矩阵
- 删除JAVA集合中元素的实现代码
- Nuclear Arms Race
- 数据结构实验之二叉树二:遍历二叉树
- TOJ 3982.Vacation
- JS中Attribute 和 property的区别
- JZOJ4683 矩阵
- 划分树
- 数据结构实验之二叉树的建立与遍历
- 3000门徒内部训练绝密视频(泄密版)第9课:彻底实战详解使用IntelliJ IDEA下的Spark程序开发
- ubuntu下搭建android开发环境(一)安装ubuntu系统(by 星空武哥)
- 我的开发之路-与你同行
- java中ArrayList 、LinkList的区别分析---程序中设比较时间
- struts2+spring+mybatis datagrid增删改查以及分页的实现
- 文件操作-按行加密解密