码迷,mamicode.com
首页 > 其他好文 > 详细

CF526D Om Nom and Necklace

时间:2020-07-01 23:45:27      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:aaa   否则   lang   最小   main   can   code   amp   转化   

gate

用时:反正挺久的

给定长度为\(n\)的字符串和整数\(k\),问每个前缀能否拆成\(ABABA\)\(B\)可以为空,即\(AAAAA\))(\(k+1\)\(A\))的形式。
\(AB\)\(S\),则\(A\)\(S\)的前缀。
问题转化为拆成\(SSSSA\)\(SSSSS\)
\(KMP\),通过\(fail\)数组可以求出最小循环节长度为\(n-f[n]\)
字符串中共有\(sum = n/(n-f[n])\)个最小循环节。
即,\(S\)的长度为\(sum/k\)\(A\)的长度为\(sum\%k\)\(B\)的长度为\(sum/k-sum\%k\)
\(n\%(n-f[n])\not=0\),即字符串不是恰好由\(n-f[n]\)的循环组成的,形式为\(SSSSA\)
则必须有\(B\)的长度\(>0\)
否则若\(n\%(n-f[n])=0\),即可能为\(SSSSS\)
则有\(B\)的长度\(\ge0\)

注意这里\(KMP\)的写法。
code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#define MogeKo qwq
using namespace std;

const int maxn = 1e6+10;
int n,k,f[maxn];
char s[maxn];

void getf() {
	for(int i = 2,j = 0; i <= n; i++) {
		while(j && s[i] != s[j+1]) j = f[j];
		if(s[i] == s[j+1]) j++;
		f[i] = j;
	}
}

int main() {
	scanf("%d%d",&n,&k);
	scanf("%s",s+1);
	getf();
	for(int i = 1; i <= n; i++) {
		int sum = i/(i-f[i]);
		if(i%(i-f[i]) != 0)
			if(sum/k > sum%k) printf("1");
			else printf("0");
		else if(sum/k >= sum%k) printf("1");
			 else printf("0");
	}
	return 0;
}

CF526D Om Nom and Necklace

标签:aaa   否则   lang   最小   main   can   code   amp   转化   

原文地址:https://www.cnblogs.com/mogeko/p/13222171.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!