zoukankan      html  css  js  c++  java
  • b_51_字符串中的最大值(next数组+倒序递推)

    一个字符串的前缀是指包含该字符第一个字母的连续子串,例如: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,是所有前缀中最大的。

    思路
    利用nx[j]表示,子串t[0:j]中最长公共前后缀的长度,假如当前位置j所对应的子串为t[0:j]
    t[0:j]中有后缀t[k:j],则nx[j]=len时,则证明前缀t[0:len]和t[k:j]是相等的,也就是出现了两次
    依次类推(根据next数组使指针倒退的含义,我们应该倒着做)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    ll n,ans,nx[N],f[N];
    void get_nx(char s[]) {
        for (int i=2,j=0; i<=n; i++) {
            while (j && s[i]!=s[j+1]) j=nx[j];
            if (s[i]==s[j+1]) j++;
            nx[i]=j;
        }
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        char s[N]; cin>>s+1;
        n=strlen(s+1);
        get_nx(s);
        for (int i=1; i<=n; i++) f[i]=1;
        for (int i=n; i; i--) f[nx[i]]+=f[i];
        for (int i=1; i<=n; i++) ans=max(ans,i*f[i]);
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    十三 .Django(ORM表高级操作)
    十二 .Django ForeighKey自关联(ORM)
    十二 .Django 一对多表ForeighKey(ORM)
    十一 .Django 一对一表OneToOneField (ORM)
    十 .Django 单表操作(ORM)
    八 .Django 模型(models)
    【模板】Lucas定理
    【模板】AC自动机加强版
    【模板】AC自动机
    【POJ3162】Walking Race 树形dp+单调队列+双指针
  • 原文地址:https://www.cnblogs.com/wdt1/p/13864858.html
Copyright © 2011-2022 走看看