• Hackerrank--String Function Calculation(后缀数组)


    题目链接

    Jane loves string more than anything. She made a function related to the string some days ago and forgot about it. She is now confused about calculating the value of this function. She has a string T with her, and value of string S over function f can be calculated as given below:

    f(S)=|S|NumberoftimesSoccuringinT

    Jane wants to know the maximum value of f(S) among all the substrings (S) of string T. Can you help her?

    Input Format
    A single line containing string T in small letter('a' - 'z').

    Output Format
    An integer containing the value of output.

    Constraints
    1 ≤|T|≤ 105

    Sample Input #00

    aaaaaa
    

    Sample Output #00

    12
    

    Explanation #00

    f('a') = 6
    f('aa') = 10
    f('aaa') = 12
    f('aaaa') = 12
    f('aaaaa') = 10
    f('aaaaaa') = 6
    

    Sample Input #01

    abcabcddd
    

    Sample Output #01

    9
    

    Explanation #01

    f("a") = 2
    f("b") = 2
    f("c") = 2
    f("ab") = 4
    f("bc") = 4
    f("ddd") = 3
    f("abc") = 6
    f("abcabcddd") = 9
    

    Among the function values 9 is the maximum one.

    题意:求字符串所有子串中,f(s)的最大值。这里s是某个子串,f(s) = s的长度与s在原字符串中出现次数的乘积。

    求得lcp, 转化为求以lcp为高的最大子矩形。

    Accepted Code:

     1 #include <string>
     2 #include <iostream>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int MAX_N = 100002;
     7 int sa[MAX_N], rk[MAX_N], lcp[MAX_N], tmp[MAX_N], n, k;
     8 
     9 bool compare_sa(int i, int j) {
    10     if (rk[i] != rk[j]) return rk[i] < rk[j];
    11     int ri = i + k <= n ? rk[i + k] : -1;
    12     int rj = j + k <= n ? rk[j + k] : -1;
    13     return ri < rj;
    14 }
    15 
    16 void construct_sa(const string &S, int *sa) {
    17     n = S.length();
    18     for (int i = 0; i <= n; i++) {
    19         sa[i] = i;
    20         rk[i] = i < n ? S[i] : -1;
    21     }
    22     
    23     for (k = 1; k <= n; k *= 2) {
    24         sort(sa, sa + n + 1, compare_sa);
    25         
    26         tmp[sa[0]] = 0;
    27         for (int i = 1; i <= n; i++) {
    28             tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
    29         }
    30         for (int i = 0; i <= n; i++) rk[i] = tmp[i];
    31     }
    32 }
    33 
    34 void construct_lcp(const string &S, int *sa, int *lcp) {
    35     n = S.length();
    36     for (int i = 0; i <= n; i++) rk[sa[i]] = i;
    37     
    38     int h = 0;
    39     lcp[0] = 0;
    40     for (int i = 0; i < n; i++) {
    41         int j = sa[rk[i] - 1];
    42         
    43         if (h > 0) h--;
    44         for (; i + h < n && j + h < n; h++) if (S[i + h] != S[j + h]) break;
    45             
    46         lcp[rk[i] - 1] = h;
    47     }
    48 }
    49 
    50 string S;
    51 int lft[MAX_N], rgt[MAX_N], st[MAX_N], top;
    52 void solve() {
    53     construct_sa(S, sa);
    54     construct_lcp(S, sa, lcp);
    55     
    56     lcp[n] = n - sa[n];
    57    // for (int i = 1; i <= n; i++) cerr << lcp[i] << ' ';
    58    // cerr << endl;
    59     top = 0;
    60     for (int i = 1; i <= n; i++) {
    61         while (top && lcp[st[top-1]] >= lcp[i]) top--;
    62         if (top) lft[i] = st[top - 1] + 1;
    63         else lft[i] = 1;
    64         st[top++] = i;
    65     }
    66     top = 0;
    67     for (int i = n; i > 0; i--) {
    68         while (top && lcp[st[top-1]] >= lcp[i]) top--;
    69         // attention: rgt[i] should be asigned to st[top - 1]
    70         // rather than st[top - 1] - 1 because lcp[i] is the
    71         // length of the longest common prefix of sa[i] and sa[i + 1]. 
    72         if (top) rgt[i] = st[top - 1];
    73         else rgt[i] = n;
    74         st[top++] = i;
    75     }
    76     long long ans = n;
    77     for (int i = 1; i <= n; i++) ans = max(ans, (long long)lcp[i] * (rgt[i] - lft[i] + 1));
    78     cout << ans << endl;
    79 }
    80 
    81 int main(void) {
    82     //ios::sync_with_std(false);
    83     while (cin >> S) solve();
    84     return 0;
    85 }
  • 相关阅读:
    买卖股票的最佳时机
    删除排序数组中的重复数字
    软件工程第五次作业:个人总结
    软件工程第二次作业——结对编程
    第一次软件工程作业补充plus
    第二次(四则运算,)
    我的第一次
    软件工程--个人总结
    软件工程第二次作业—结对编程
    软件工程第一次作业补充
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/3930096.html
Copyright © 2020-2023  润新知