HDU 6740 kmp最小循环节

题意:
给一个无线循环小数的前几位,给n,m

选择其中一种出现在前几位的循环节方式(a个数),循环节的长度b

使得n*a-m*b最大

样例:

2 1

12.1212

输出 6 

选择2,2*1-1*1=1;

选择12,2*4-2*1=6;

选择21,2*3-2*1=4;

选择212,2*3-3*1=3;

选择1212,2*4-4*1=4;

思路:

将小数部分,倒过来,求每个点的最小循环节,kmp中i-next[i]代表最小循环节

当倒过来的小数部分,n*i-m*(i-next[i])中的最大就是答案

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=1e7+10;
ll n,m;
int nexts[maxn];
char s[maxn],s2[maxn];
int p2=0;
il void GetNext(int l){
    int i=0;
    int j=-1;
    nexts[0]=-1;
    while(i<l){
        if(j==-1 || s2[i]==s2[j]){
            i++;
            j++;
            nexts[i] = j;
        }
        else
            j = nexts[j];
    }
    return;
}
int main(){
    while(~scanf("%lld%lld",&n,&m)){
        scanf("%s",s);
        int l=strlen(s);p2=0;
        int i;
        for(i=0;i<l;i++){
            if(s[i]=='.'){
                break;
            }
        }
        for(int k=l-1;k>i;k--){
            s2[p2++]=s[k];
        }
        GetNext(p2);
        ll maxx=-1e18;
        for(i=1;i<=p2;i++){
            maxx=max(maxx,(ll)i*n-(ll)(i-nexts[i])*m);
            //cout<<i<<" "<<(i-nexts[i])<<endl;
        }
        printf("%lld\n",maxx);
    }
    return 0;
}

 

 

kmp模板

 

inline void getnext(char *ss){
    mem(ne,0);
    int l=strlen(ss);
    int i=0,j=-1;ne[0]=-1;
    while(i<l){
        if (j == -1 || ss[i] == ss[j])
        {
            i++;
            j++;
            ne[i] = j;
        }
        else{
            j = ne[j];
        }
    }
    return;
}
inline int kmp(char *ss,char *s){
    int l=strlen(s),ls=strlen(ss);
    int i=0,j=0,ans=0;
    while(i<l){
        if(j==-1||s[i]==ss[j])
        {
            i++;
            j++;
        }
        else
            j=ne[j];
        if(j==ls)
        {
            ans++;
            j=ne[j];
        }
    }
    return ans;
}

 

 待补全

模板

 

int next[maxn];
string str[maxn];
void get_next(string s){
    memset(next,0,sizeof(next));
    int len=s.length();
    int i,j;
    j=next[0]=-1;
    i=0;
    while(i<len){
        while(j!=-1&&s[i]!=s[j]) j=next[j];
        next[++i]=++j;
    }
}
bool kmp(string a,string b){
    int lena=a.length();
    int lenb=b.length();
    get_next(b);
    int i=0,j=0;
    while(i<lena){
        while(j!=-1&&a[i]!=b[j]) j=next[j];
        i++,j++;
        if(j>=lenb) return true;
    }
    return false;
}

 

posted @ 2020-02-27 18:56  ouluy  阅读(200)  评论(0编辑  收藏  举报