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]来说 ...
随机推荐
- php环境一键升级脚本
因为要解析PHP页面需要配置相应的PHP环境,而系统本身的php版本又大多不合适.网上那种一键lamp和lnmp的脚本很多,但是这样一来自己能够定制的空间则少了.所以我自己编写了个门用于安装php环境 ...
- if 条件的 true / false 及 select 的值
if 条件的 true / false 任何不是 false, undefined, null, 0, NaN 的值,或一个空字符串('')在作为条件语句进行测试时实际返回true,因此您可以简单地使 ...
- Mockito 中文文档 ( 2.0.26 beta )
Mockito 中文文档 ( 2.0.26 beta ) 由于缺乏校对,难免有谬误之处,如果发现任何语句不通顺.翻译错误,都可以在github中的项目提出issue.谢谢~ Mockito框架官方地址 ...
- 【快学springboot】SpringBoot整合Mybatis Plus
原创声明 本文首发于头条号[Happyjava].Happy的掘金地址:https://juejin.im/user/5cc2895df265da03a630ddca,Happy的个人博客:http: ...
- C. Swap Letters 01字符串最少交换几次相等
C. Swap Letters time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- A*算法和K短路(A*)
堪称最好的A算法 https://blog.csdn.net/b2b160/article/details/4057781 K短路(A) https://www.jianshu.com/p/27019 ...
- 02.Scala高级特性:第6节 高阶函数;第7节 隐式转换和隐式参数
Scala高级特性 1. 课程目标 1.1. 目标一:深入理解高阶函数 1.2. 目标二:深入理解隐式转换 2. 高阶函数 2.1. 概念 Scala混合了面向对象和函数式的特 ...
- 移动端一像素边框解决方案[css scale]
新建一个border.css的文件,然后将代码复制粘贴,然后引用border.css样式文件,然后给需要添加边框的元素,加相应的类样式. tips: border-bottom[一像素下边框]:bor ...
- 「APIO2012」派遣
「APIO2012」派遣 传送门 当预算超过限制时,优先丢掉薪水高的忍者(左偏树维护一下),然后答案取合法答案的最大值. 参考代码: #include <algorithm> #inclu ...
- 用C语言写一个Helloworld_实现第一步编译运行
编写第一个hello world 创建helloworld.c // 程序头文件 #include <stdio.h> // 主入口函数 int main(int arc, char* a ...