Gym 101667 Problem I.Slot Machines (kmp + 最小循环节)

链接:I.Slot Machines
题意:
每次给出数组 a 。问要满足从第k+1个数开始,数组T开始以p个数为一个循环,k+p最小是多少。如果存在多个k+p最小,输出p最小的方案。
思路:

  1. 枚举每一个 k 求出 [k + 1 , n] 的循环节长度就好了 , 可以用 kmp 求出循环节长度 , 我们先求出nex数组 , 对于后 i 个数的 p 值 就是 i - nex[i].
    代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int mod = 998244353;
int s[maxn];
int nex[maxn],n;
void getnext(){
	nex[0] = -1;
	int i = 0,j = -1;
	while(i <= n){
		if(j == -1 || s[i] == s[j]){
			i ++;
			j ++;
			nex[i] = j;
		}
		else j = nex[j];
	}
}
int cal(int len){            // 计算长度为 前 len 个字符的循环节 , 不一定完整 如abcabca 会返回 3.
    return  len - nex[len];
}
int main (){
   scanf("%d",&n);
   for(int i = 0; i < n; i ++){
       scanf("%d",&s[i]);
   }
   reverse(s ,s + n);
   getnext();
   int ans1,ans2;
   for(int i = 1; i <= n; i ++){
       if(cal(i) + n - i < ans1 + ans2){
          ans1 = cal(i);
          ans2 = n - i;
       }
       else if(cal(i) + n - i == ans1 + ans2){
            if(ans1 > cal(i)){
                ans1 = cal(i);
            }
       }
   }
  printf ("%d %d\n",ans2,ans1);
}

  1. 如果在某些题里遇到要求最小循环节的题目,我们就要判断总长度是否能被这个 p 整除。
    链接: 最小循环节

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int mod = 998244353;
char s[maxn];
int nex[maxn],n;
int T;
void getnext(){
	nex[0] = -1;
	int i = 0,j = -1;
	while(i <= n){
		if(j == -1 || s[i] == s[j]){
			i ++;
			j ++;
			nex[i] = j;
		}
		else j = nex[j];
	}
}
int cal(int len){              // 计算长度为 前 len 个字符的循环节 , 不一定完整 如abcabca 会返回 3.
    return  len - nex[len];
}
int main (){
   scanf("%d",&T);
   while(T--){
        scanf("%s",s);
        memset(nex,0,sizeof(nex));
        n = strlen(s);
        getnext();
        int ans = cal(n);
        if(n % ans  == 0){
            printf ("%d\n",ans);
        }
        else printf ("%d\n",n);
        if(T!=0) printf ("\n");

   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值