jzoj 4683. 【GDOI2017模拟8.11】矩阵 后缀数组+哈希表
来源:互联网 发布:apache 安装 编辑:程序博客网 时间:2024/04/19 11:49
题意:求一个矩阵中有多少不同的子矩阵
分析:枚举宽度 w,hash[i][j]表示,表示第 i 行,从第 j 个字符开始的 w 个字符的哈希值。然后把起点相同的列,连在一起,也就是竖着把每一列连在一起,列与列之间用一个特殊字符隔开,变成了一个串剩下的就是求这个串有多少个不同的子串。用后缀数组来求子串种数。
时间复杂度: O(n^3log^2n)
代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 120#define MOD1 2477#define MOD2 2969#define ll long longusing namespace std;int n,m,s[N*N],b[MOD1*MOD2],c[N*N],d[N*N],sa[N*N],rank[N*N],height[N*N],l[N*N],hash[N][N],hash1[N][N],hash2[N][N];int v[MOD1][MOD2],cnt;char c1[N],ch[N][N];void getsa(int n,int m){for (int i=0;i<=m;i++) b[i]=0;for (int i=1;i<=n;i++) b[s[i]]++;for (int i=1;i<=m;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) c[b[s[i]]--]=i;int t=0;for (int i=1;i<=n;i++){if (s[c[i]]!=s[c[i-1]]) t++;rank[c[i]]=t;}int j=1;while (j<=n){for (int i=0;i<=n;i++) b[i]=0;for (int i=1;i<=n;i++) b[rank[i+j]]++;for (int i=1;i<=n;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) c[b[rank[i+j]]--]=i;for (int i=0;i<=n;i++) b[i]=0;for (int i=1;i<=n;i++) b[rank[i]]++;for (int i=1;i<=n;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) d[b[rank[c[i]]]--]=c[i];int t=0;for (int i=1;i<=n;i++){if (rank[d[i]]!=rank[d[i-1]]||rank[d[i]]==rank[d[i-1]]&&rank[d[i]+j]!=rank[d[i-1]+j]) t++;c[d[i]]=t;}for (int i=1;i<=n;i++) rank[i]=c[i];if (t==n) break;j*=2;}for (int i=1;i<=n;i++) sa[rank[i]]=i;}void getheight(int n){int k=0;for (int i=1;i<=n;i++){if (k) k--;int j=sa[rank[i]-1];while (i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;height[rank[i]]=k;}}int getans(int n){int ans=0;for (int i=1;i<=n;i++)ans+=l[sa[i]]-height[i];return ans;}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){scanf("%s",c1);for (int j=1;j<=m;j++)ch[i][j]=c1[j-1];}int ans=0;for (int w=1;w<=m;w++){for (int i=1;i<=n;i++)for (int j=1;j<=m-w+1;j++){hash1[i][j]=(hash[i][j]*26+ch[i][j+w-1]-'A')%MOD1;hash2[i][j]=(hash[i][j]*26+ch[i][j+w-1]-'A')%MOD2;int x=hash1[i][j],y=hash2[i][j];if (!v[x][y]) v[x][y]=++cnt;hash[i][j]=v[x][y];}int len=0,hehe=cnt;for (int j=1;j<=m-w+1;j++){if (j>1){s[++len]=++hehe;l[len]=0;}for (int i=1;i<=n;i++){s[++len]=hash[i][j];l[len]=n-i+1;}}memset(rank,0,sizeof(rank));getsa(len,hehe);getheight(len);ans+=getans(len);}printf("%d",ans);return 0;}
0 0
- jzoj 4683. 【GDOI2017模拟8.11】矩阵 后缀数组+哈希表
- jzoj 4690. 【GDOI2017模拟8.12】字符串 后缀数组+RMQ
- 【jzoj5084】【GDOI2017第四轮模拟day1】【子串】【后缀数组】
- jzoj 4684. 【GDOI2017模拟8.11】卡牌游戏 线段树
- jzoj 5052. 【GDOI2017模拟二试4.12】旅游路线 广义后缀自动机
- JZOJ 4863. 【GDOI2017模拟11.5】Market
- JZOJ 4863 【GDOI2017模拟11.5】Market
- jzoj【GDOI2017第二轮模拟day2】开房间
- JZOJ 100037【NOIP2017提高A组模拟7.11】后缀数组
- 【GDOI2017模拟8.11】总结
- 【GDOI2017模拟8.11】选择
- 【GDOI2017模拟8.11】生物学家
- jzoj 4690. 【GDOI2017模拟8.12】躲藏 网络流
- jzoj 4702. 【GDOI2017模拟8.15】Game 状压dp+减枝
- jzoj 4718. 【GDOI2017模拟7.20】准备食物2 费用流
- JZOJ 4739 【雅礼联考GDOI2017模拟9.2】Ztxz16学图论
- jzoj 4848. 【GDOI2017模拟11.3】永恒的契约 单调栈
- JZOJ 4915. 【GDOI2017模拟12.9】最长不下降子序列
- 哈理工OJ 1795 发现王国之旅(最小生成树)
- lstm的数学推导
- 蓝牙连接建立
- Dagger2使用进阶
- 读取common.properties文件
- jzoj 4683. 【GDOI2017模拟8.11】矩阵 后缀数组+哈希表
- Android开源库之使用ZXing开源库实现二维码功能
- 爬虫抓取美团网上所有商家信息
- oracle 启动监听提示 :The listener supports no services
- 重建二叉树
- 简单了解字符与字符集
- 测试
- 导入c标签等,以及${pageContext.request.contextPath}的作用
- List数据生成CSV文件