CF526D Om Nom and Necklace
本题有翻译……
我一开始又有一种沙雕做法……就是每次暴力匹配next的next……(具体操作很诡异,显然它凉了)
我们后来发现,如果把AB看成一个循环节的话,那就相当于问这个字符串能否被拆成k个AB串+一个AB串的前缀(前缀可以为空)
特别的,他也可以被看作能否拆成k+1个循环节。
我们把字符串看成SSSSSSSS……SST,其中T是S的前缀。我们假设S在字符串中出现了R次。既然出现了k个AB串,那么也就是说相当于每份AB中出现了R/k个S,那么剩余的R%k就属于A了,那么B中就有R/k-R%k个S。当然循环节是用kmp求出i-next[i]得到的。
当T=S,即B可以为空的时候,我们满足R/k-R%k>=0即可。
T!=S,即B不可为空的时候,我们满足上式大于0才可以。
之后我们就确定了这个01串,可以输出答案了。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 10005; const int N = 1000005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int n,cur,last,nxt[N],k; char s[N],t[N]; bool ans[N]; void getnext() { int j = 0; rep(i,2,n) { while(j && s[j+1] != s[i]) j = nxt[j]; if(s[j+1] == s[i]) j++; nxt[i] = j; } } int main() { n = read(),k = read(); scanf("%s",s+1); getnext(); //rep(i,1,n) printf("%d ",nxt[i]);enter; rep(i,1,n) { int r = i - nxt[i]; if(i % r == 0) { int d = i / r; if(d / k - d % k >= 0) ans[i] = 1; } else { int d = i / r; if(d / k - d % k > 0) ans[i] = 1; } } rep(i,1,n) printf("%d",ans[i]);enter; return 0; }
当你意识到,每个上一秒都成为永恒。