51Nod 1292 字符串中的最大值 V2 后缀数组 + 单调栈

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


题目:

https://vjudge.net/problem/51Nod-1292

题意:

有一个字符串T。字符串S的F函数值可以如下计算:F(S) = L * S在T中出现的次数(L为字符串S的长度)。求所有T的子串S中,函数F(S)的最大值。
Input
输入字符串T, (1 <= L <= 1000000, L为T的长度),T中的所有字符均为小写英文字母。
Output
输出T的所有子串中长度与出现次数的乘积的最大值。
Input示例
aaaaaa
Output示例
12

思路:

用后缀数组求出height数组,然后用单调栈求解,注意答案是long long范围

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;
const int N = 1000000 + 10, INF = 0x3f3f3f3f;

int sa[N], height[N], rnk[N], wa[N], wb[N], c[N];
char str[N];
int s[N];
int top, stk[N];
int L[N], R[N];

bool cmp(int *r, int a, int b, int l)
{
    return r[a] == r[b] && r[a+l] == r[b+l];
}
void Rsort(int *x, int *y, int n, int m)
{
    for(int i = 0; i < m; i++) c[i] = 0;
    for(int i = 0; i < n; i++) c[x[y[i]]]++;
    for(int i = 1; i < m; i++) c[i] += c[i-1];
    for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
}
void da(int *s, int n, int m)
{
    int *x = wa, *y = wb;
    for(int i = 0; i < n; i++) x[i] = s[i], y[i] = i;
    Rsort(x, y, n, m);
    for(int j = 1, p = 1; p < n; j *= 2, m = p)
    {
        p = 0;
        for(int i = n-j; i < n; i++) y[p++] = i;
        for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j;
        Rsort(x, y, n, m);
        swap(x, y); p = 1; x[sa[0]] = 0;
        for(int i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
    }
}
void get_height(int *s, int n)
{
    int i, j, k = 0;
    for(i = 0; i <= n; i++) rnk[sa[i]] = i;
    for(i = 0; i < n; height[rnk[i++]] = k)
        for(k ? --k : 0, j = sa[rnk[i]-1]; s[i+k] == s[j+k]; k++);
}
int main()
{
    scanf("%s", str);
    int len = strlen(str);
    for(int i = 0; i < len; i++) s[i] = str[i] - 'a' + 1;
    s[len] = 0;
    da(s, len+1, 30);
    get_height(s, len);
    top = 0;
    for(int i = 2; i <= len; i++)
    {
        while(top > 0 && height[stk[top-1]] >= height[i]) top--;
        L[i] = top ? stk[top-1] + 1 : 2;
        stk[top++] = i;
    }
    top = 0;
    for(int i = len; i >= 2; i--)
    {
        while(top > 0 && height[stk[top-1]] >= height[i]) top--;
        R[i] = top ? stk[top-1] - 1 : len;
        stk[top++] = i;
    }
    ll ans = len;
    for(int i = 2; i <= len; i++) ans = max(ans, 1LL * (R[i] - L[i] + 2) * height[i]);
    printf("%lld\n", ans);
    return 0;
}


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6