51nod 1277 字符串中的最大值 (后缀数组求height[i])

简介: 51nod 1277 字符串中的最大值 (后缀数组求height[i])

一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd。

给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值。

例如:S = “abababa” 所有的前缀如下:


“a”, 长度与出现次数的乘积 1 * 4 = 4,

“ab”,长度与出现次数的乘积 2 * 3 = 6,

“aba”, 长度与出现次数的乘积 3 * 3 = 9,

“abab”, 长度与出现次数的乘积 4 * 2 = 8,

“ababa”, 长度与出现次数的乘积 5 * 2 = 10,

“ababab”, 长度与出现次数的乘积 6 * 1 = 6,

“abababa”, 长度与出现次数的乘积 7 * 1 = 7.


其中"ababa"出现了2次,二者的乘积为10,是所有前缀中最大的。

输入

输入字符串S, (1 <= L <= 100000, L为字符串的长度),S中的所有字符均为小写英文字母。

输出

输出所有前缀中字符长度与出现次数的乘积的最大值。

输入样例

abababa

输出样例

10

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int sa[maxn], rak[maxn];
int tx[maxn], height[maxn];
char s[maxn];
int n, m, p;
int cnt[maxn];
struct node {
  int x, y, id;
}a[maxn], b[maxn];
void rsort() {
  for (int i = 1; i <= m; i++) tx[i] = 0;
  for (int i = 1; i <= n; i++) tx[a[i].y]++;
  for (int i = 1; i <= m; i++) tx[i] += tx[i - 1];
  for (int i = 1; i <= n; i++) b[tx[a[i].y]--] = a[i];
  for (int i = 1; i <= m; i++) tx[i] = 0;
  for (int i = 1; i <= n; i++) tx[b[i].x]++;
  for (int i = 1; i <= m; i++) tx[i] += tx[i - 1];
  for (int i = n; i >= 1; i--) a[tx[b[i].x]--] = b[i];
}
void ssort() {
  rsort();
  p = 0;
  for (int i = 1; i <= n; i++) {
    if (a[i].x != a[i - 1].x || a[i].y != a[i - 1].y) ++p;
    rak[a[i].id] = p;
  }
  for (int i = 1; i <= n; i++) {
    a[i].x = rak[i];
    a[i].id = sa[rak[i]] = i;
    a[i].y = 0;
  }
  m = p;
}
void solve() {
  m = 127;
  for (int i = 1; i <= n; i++) {
    a[i].x = a[i].y = s[i];
    a[i].id = i;
  }
  ssort();
  for (int j = 1; j <= n; j <<= 1) {
    for (int i = 1; i + j <= n; i++) {
      a[i].y = a[i + j].x;
    }
    ssort();
    if (p == n) break;
  }
}
void get_Height() {
  int k = 0;
  for (int i = 1; i <= n; i++) {
    if (k) k--;
    int j = sa[rak[i] - 1];
    while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
    height[rak[i]] = k;
  }
}
int main() {
  scanf("%s", s + 1);
  n = strlen(s + 1);
  solve(); get_Height(); 
  int mm = 1e8;
  for (int i = rak[1] + 1; i <= n; i++) {
    mm = min(mm, height[i]);
    cnt[mm]++;
  }
  mm = 1e8;
  for (int i = rak[1]; i >= 1; i--) {
    mm = min(mm, height[i]);
    cnt[mm]++;
  }
  for (int i = n; i >= 1; i--) {
    cnt[i] += cnt[i + 1];
  }
  long long ans = 0;
  for (int i = 1; i <= n; i++) {
    ans = max(ans, 1LL * i * (cnt[i] + 1));
  }
  printf("%lld\n", ans);
  return 0;
}
相关文章
|
安全 Java 数据安全/隐私保护
通过java实现ldap修改AD域用户密码(最新,详细)
环境及说明,AD证书安装过程,AD证书的导出与导入,AD证书导入java密钥库中,java实现ldap改密
22752 0
|
XML 移动开发 JavaScript
JavaScriptDOM编程(基础&进阶)1
JavaScriptDOM编程(基础&进阶)1
166 0
|
11月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
1312 9
|
存储 关系型数据库 数据管理
【最佳实践】高性价比的数据归档解决方案(DMS + AnalyticDB PostgreSQL)
发布全新数据归档方案,依托DMS + AnalyticDB PostgreSQL Serverless版本,帮助客户用低价格实现海量数据的持久化,还可以对归档数据进行完善管理、高效寻回、查看并进行分析
【最佳实践】高性价比的数据归档解决方案(DMS + AnalyticDB PostgreSQL)
|
SQL 安全 API
淘东电商项目(71) -互联网安全架构设计(网关验证AccessToken)
淘东电商项目(71) -互联网安全架构设计(网关验证AccessToken)
127 0
Ansible模块介绍——计划任务模块
Ansible模块介绍——计划任务模块
273 0
|
监控 Linux
Linux系列 目录和文件管理
Linux系列 目录和文件管理
219 0
|
小程序
樱花飘落模拟器-情人节祝你表白成功
嗨!大家好,我是小蚂蚁。这是我去年做的一个漂亮的樱花飘落模拟器,你可以改编一下,然后发功给想你爱的人,祝你表白成功。
217 0
樱花飘落模拟器-情人节祝你表白成功
我用加强版RFM模型,轻松扒出B站优质up主!(含数据+实战代码)(中)
本文在RFM模型基础上做了调整,尝试用更符合b站特性的IFL模型,找到各分区优质up主。整个过程以分析项目的形式展开,最终附上了完整源数据和代码,方便感兴趣的同学练手。
362 0
我用加强版RFM模型,轻松扒出B站优质up主!(含数据+实战代码)(中)
|
存储 缓存 网络协议
TCP 基础知识(四)
Hey guys ,我是 cxuan ,欢迎你阅读我这一期的文章。
TCP 基础知识(四)