GYM 101667I Slot Machines(KMP next应用)

题意:给你n个数让你删除前k个后,剩余的数的循环节是p,例1 2 3 1 2,循环节是3,后面剩余的1 2是在1 2 3中的,也算循环

思路:之前写的暴力,一直T,主要是每次都要重新跑next数组,后来队友说可以把串翻转一下,后来懂了,随便改了改交了还是T。结束以后又重新看了看以前读的博客,才发现之前学的有些小问题。感觉老年人还什么都不会。对于一个串,len-next[len]直接得到的就是最小循环节,对于不能整除的串,有x=L-next[len]%L(L代表最小循环节)x为在串后面补x个字母后为循环节

  对已这个题我们不需要考虑最后要补几个数字,因为我们最开始把数组翻转,其实是不影响的,我们直接删去就可以了

代码:(next不需要清空)

#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+7;
int Next[maxn];
int c[maxn];
int n;
inline void getNext()
{
    int j=0,k=-1;
    Next[0]=-1;
    while(j<n){
        if(k==-1||c[j]==c[k])Next[++j]=++k;
        else k=Next[k];
    }
}
int main()
{
    while(~scanf("%d",&n)){
        for(int i=n-1;i>=0;i--){
            scanf("%d",&c[i]);
        }
        getNext();
        int ansk,ansp;
        ansk=n-1,ansp=1;
        for(int i=0;i<=n;i++){
            int p=i-Next[i],k=n-i;
            if(p+k<ansk+ansp) ansk=k,ansp=p;
            else if(p+k==ansk+ansp&&p<ansp) ansk=k,ansp=p;
        }
        printf("%d %d\n",ansk,ansp);
    }
    return 0;
}
/*
14
1 2 1 2 3 5 6 1 2 3 5 6 1 2

6
612534 3157 423 3157 423 3157

5
1 2 3 1 2
*/

 

posted @ 2018-10-04 18:48  啦啦啦天啦噜  阅读(323)  评论(0编辑  收藏  举报