[51nod 1129] 字符串最大值(kmp)

传送门

题目大意

求一个字符串的前

缀出现次数乘以长度的最大值。

题解

暴力枚举每一个前缀求出现次数再乘以常数取最大 这样做会T几个点

看了老师的做法是任意前缀出现的次数,它的next也会出现这些次数

代码

暴力

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[1000009];
int nex[1000009],len;
long long max_ans;
void getnext(){
    for(int i=2,j=0;i<=len;i++){//从2开始啊,扎心了老铁 
        while(s[i]!=s[j+1]&&j)j=nex[j];
        if(s[i]==s[j+1])nex[i]=++j;
    }
}
void slove(int k){
    int js=0;
    for(int i=1,j=0;i<=len;i++){
        while(s[i]!=s[j+1]&&j)j=nex[j];
        if(s[i]==s[j+1])++j;
        if(j==k){
            js++;j=nex[j];
        }
    }
//    cout<<k<<" "<<js<<" "<<js*k<<endl;
    max_ans=max(max_ans,(long long)js*k);
}
int main(){
    ios::sync_with_stdio(0);
    freopen("string_maxval.in","r",stdin);
    freopen("string_maxval.out","w",stdout); 
    scanf("%s",s+1);
    len=strlen(s+1);
    getnext();
    for(int i=1;i<=len;i++)slove(i);
    printf("%lld
",max_ans);
    return 0;
}

第二种方法

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

using namespace std;
const int maxl=1000010;
char s[maxl],su[maxl];
int next[maxl],l,ans=0,cs[maxl];
void getnext()
{
    next[0]=-1;
    l=strlen(s);
    for(int j,i=1;i<l;i++)
    {
        j=next[i-1];
        while(s[i]!=s[j+1]&&j>=0)j=next[j];
        next[i]=s[i]==s[j+1]?j+1:-1;
    }
}
int main()
{
    freopen("string_maxval.in","r",stdin);
    freopen("string_maxval.out","w",stdout);
    scanf("%s",s);
    getnext();
    for(int i=l-1;i>=0;--i)
    {
        cs[i]++;
        cs[next[i]]+=cs[i];
        if(cs[i]*(i+1)>ans)ans=cs[i]*(i+1);
    }
    cout<<ans;
    fclose(stdin);fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/zzyh/p/7354403.html