zoukankan      html  css  js  c++  java
  • 51nod 1277字符串中的最大值(拓展kmp)

    题意:
    一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd。
    给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值。
     
    题解:
    我们前缀匹配的位置个数随长度是递减的(即长度越长,位置越少)。
    用拓展kmp对自身求Next数组
    我们就知道了每个前缀能匹配的最大后缀的那些位置
    然后按照匹配长度倒序相加即是匹配的位置个数。
     
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int maxn = 1e6 + 100;
    char S[maxn];
    int Next[maxn], extend[maxn];
    void GetNext(char *T, int *Next){
        int len = strlen(T);
        Next[0] = len;
        int a, p;
        for(int i = 1, j = -1; i < len; i++, j--){
           if(j < 0 || i + Next[i-a] >= p){
                if(j < 0) p = i, j = 0;
                while(p < len && T[p] == T[j])
                    p++, j++;
                Next[i] = j;
                a = i;
           } else Next[i] = Next[i-a];
        }
    }
    void GetExtend(char *S, char *T, int *extend, int *Next){
        GetNext(T, Next);
        int a, p;
        int slen = strlen(S), tlen = strlen(T);
        for(int i = 0, j = -1; i < slen; i++, j--){
            if(j < 0 || i + Next[i-a] >= p){
                if(j < 0) p = i, j = 0;
                while(p < slen && j < tlen && S[p] == T[j]) p++, j++;
                extend[i] = j;
                a = i;
            } else extend[i] = Next[i-a];
        }
    }
    int Num[maxn];
    int main(){
        cin>>S;
        int len = strlen(S);
        GetNext(S, Next);
        for(int i = 0; i < len; i++) Num[Next[i]]++;
        long long ans = 0, n = 0;
        for(int i = len; i >= 1; i--){
            n += Num[i];
            ans = max(ans, n*i);
        }
        cout<<ans<<endl;
    }
     
     
  • 相关阅读:
    纯前端导出Excel表格
    vue 组件按需引用,vue-router懒加载,vue打包优化,加载动画
    解决图片循环展示间距
    微信小程序aes前后端加密解密交互
    判断字符串中是否包含表情
    银行卡号Luhn校验算法
    身份证校验(支持15位和18位身份证号)、邮箱校验正则
    数组去重
    bootstrap 中 css 与 javascript 的使用
    js 分页
  • 原文地址:https://www.cnblogs.com/Saurus/p/7637707.html
Copyright © 2011-2022 走看看