Samjia 和矩阵[loj6173](Hash+后缀数组)
本题要求本质不同的子矩阵,即位置不同也算相同(具体理解可以看样例自己yy)。
我们先看自己会什么,我们会求一个字符串中不同的子串的个数。我们考虑把子矩阵变成一个字符串。
先枚举矩阵的宽度,记为w(1<=w<=m)。再把一行之内的连续的w的字符用字符串hash哈成一个整数,再把这个整数hash成一个较小的数(相当于之前字符串的一个字符)。

把最后完成的矩阵在把没一列接起来,形成一个字符串(每列后要加一个字符如:1 2 3 4 2 3 3 5)。然后对这个串求我们会的子串个数(减去height值)即可。
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll N = , M = ;
const ull P = ;
ll len, tot, ans;
ll n, m;
ll s[N * M], rnk[N * M], sa[N * M], sum[N * M], v1[N * M], v2[N * M], height[N * M];
char arr[N][M];
ull _hash[N][M];
map<ull, ll> mp;
bool cmp(ll *t, ll a, ll b, ll l) {
return t[a] == t[b] && t[a + l] == t[b + l];
}
void da() {
ll i, j, p = ;
for (i = ; i <= tot; i++) sum[i] = ;
for (i = ; i <= len; i++) sum[rnk[i] = s[i]]++;
for (i = ; i <= tot; i++) sum[i] += sum[i - ];
for (i = len; i >= ; i--) sa[sum[rnk[i]]--] = i;
for (j = ; j <= len; j *= , tot = p) {
for (p = , i = len - j + ; i <= len; i++) v2[++p] = i;
for (i = ; i <= len; i++) if (sa[i] > j) v2[++p] = sa[i] - j;
for (i = ; i <= len; i++) v1[i] = rnk[v2[i]];
for (i = ; i <= tot; i++) sum[i] = ;
for (i = ; i <= len; i++) sum[v1[i]]++;
for (i = ; i <= tot; i++) sum[i] += sum[i - ];
for (i = len; i >= ; i--) sa[sum[v1[i]]--] = v2[i];
for (swap(rnk, v2), rnk[sa[]] = , i = , p = ; i <= len; i++) {
rnk[sa[i]] = cmp(v2, sa[i - ], sa[i], j) ? p - : p++;
}
}
}
void calheight() {
ll i, j, p = ;
for (i = ; i <= len; i++) {
if (p) p--;
j = sa[rnk[i] - ];
while (s[i + p] == s[j + p]) p++;
height[rnk[i]] = p;
}
}
ull ksm[];
int main() {
ksm[] = ;
for (int i = ; i <= ; i++) {
ksm[i] = ksm[i - ] * P;
}
scanf("%lld%lld", &n, &m);
for (ll i = ; i <= n; i++) {
scanf("%s", arr[i] + );
for (ll j = ; j <= m; j++) {
_hash[i][j] = _hash[i][j - ] * P + arr[i][j] - 'A' + ;
}
}
for (ll w = ; w <= m; w++) {
tot = , len = ;
mp.clear();
for (ll j = ; j + w - <= m; j++) {
for (ll i = ; i <= n; i++) {
ull tmp = _hash[i][j + w - ] - _hash[i][j - ] * ksm[w];
if (mp[tmp] == ) {
mp[tmp] = ++tot;
}
s[++len] = mp[tmp];
}
s[++len] = ++tot;
}
da();
calheight();
ans += n * (n + ) / * (m - w + );
for (ll i = ; i <= len; i++) {
ans -= height[i];
}
}
cout << ans;
return ;
}
Samjia 和矩阵[loj6173](Hash+后缀数组)的更多相关文章
- liberOJ #6173. Samjia 和矩阵 hash+后缀数组
#6173. Samjia 和矩阵 题目链接 : 点这里 题目描述 给你一个只包含大写字母的矩阵,求有多少本质不同的子矩阵. 输入格式 第一行包含两个整数 nnn , mmm ,表示矩阵 nnn 行 ...
- [USACO07DEC]Best Cow Line G 字符串hash || 后缀数组
[USACO07DEC]Best Cow Line G [USACO07DEC]Best Cow Line G 小声哔哔:字符串hash牛逼 题意 给出一个字符串,每次可以从字符串的首尾取出一个字符, ...
- BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)
转博客大法好 自己画一画看一看,就会体会到这个设置关键点的强大之处了. CODE(sa) O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms #inclu ...
- loj6173 Samjia和矩阵(后缀数组/后缀自动机)
题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...
- HDU-4622 Reincarnation 后缀数组 | Hash,维护和,扫描
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4622 题意:给一个字符串,询问某字串的不同字串的个数. 可以用后缀数组来解决,复杂度O(n).先求出倍 ...
- UVALive - 4513 Stammering Aliens ——(hash+二分 || 后缀数组加二分)
题意:找一个出现了m次的最长子串,以及这时的最右的位置. hash的话代码还是比较好写的,,但是时间比SA多很多.. #include <stdio.h> #include <alg ...
- Uva12206 Stammering Aliens 后缀数组&&Hash
Dr. Ellie Arroway has established contact with an extraterrestrial civilization. However, all effort ...
- Hash(LCP) || 后缀数组 LA 4513 Stammering Aliens
题目传送门 题意:训练指南P225 分析:二分寻找长度,用hash值来比较长度为L的字串是否相等. #include <bits/stdc++.h> using namespace std ...
- acdream1116 Gao the string!(hash二分 or 后缀数组)
问题套了一个斐波那契数,归根结底就是要求对于所有后缀s[i...n-1],所有前缀在其中出现的总次数.我一开始做的时候想了好久,后来看了别人的解法才恍然大悟.对于一个后缀来说 s[i...n-1]来说 ...
随机推荐
- Codeforces Round #617 (Div. 3)
A 题意:能否将数组里面的值用数组里面的值替换出一个和为奇数的数组 思路:1.和为奇数yes 2.和为偶数但有奇数yes 3.个数是奇数的,有奇数的yes 其他都是no 果然罚时全给了A #inclu ...
- vue.js 强行赋值、刷新数组或者对象 方法之 $.set()
实际开发过程中,数据交互的的时候需要赋值,刷新,但是不可能每次赋值之后都刷新整个页面,所以就要用到 vue.js方法 $.set(),能实现赋值对象的局部刷新 语法:Vue.set(object, k ...
- redhat7.6 DNS配置正向解析
1.安装DNS服务 yum install bind yum install bind-chroot 安装完的配置文件/etc/named.conf 启动systemctl start named.s ...
- [python]python中的一些包以及他们的基本用处和安装
pika可以用来连接rabbitmqpip install pika -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com ...
- 解Bug之路-记一次调用外网服务概率性失败问题的排查
前言 和外部联调一直是令人困扰的问题,尤其是一些基础环境配置导致的问题.笔者在一次偶然情况下解决了一个调用外网服务概率性失败的问题.在此将排查过程发出来,希望读者遇到此问题的时候,能够知道如何入手. ...
- Spark以yarn方式运行时抛出异常
Spark以yarn方式运行时抛出异常: cluster.YarnClientSchedulerBackend: Yarn application has already exited with st ...
- 5-create-react-app整合antDesign功能
使用ant-design: 首先创建react项目: create-react-app app cd app 其次 AntDesign的高级配置:按需导入组件,自定义主题 1.下载依赖(利用yarn, ...
- 吴裕雄--天生自然PYTHON爬虫:使用Selenium爬取大型电商网站数据
用python爬取动态网页时,普通的requests,urllib2无法实现.例如有些网站点击下一页时,会加载新的内容,但是网页的URL却没有改变(没有传入页码相关的参数),requests.urll ...
- C++打开文件夹
https://bbs.csdn.net/topics/392055617?page=1 见2楼 system("start \"\" \"文件夹路径\&q ...
- 【PAT甲级】1013 Battle Over Cities (25 分)(并查集,简单联通图)
题意: 输入三个整数N,M,K(N<=1000,第四个数据1e5<=M<=1e6).有1~N个城市,M条高速公路,K次询问,每次询问输入一个被敌军占领的城市,所有和该城市相连的高速公 ...