簡要題意:
給一個字符環,長度爲 ,請你對 ,回答,能否刪去一個長度爲 的子串,使得剩下部分首尾相接之後,任何相鄰的兩個位置字符不同。
題解:
考慮剩什麼而不是刪什麼。
容易發現我們把存在相鄰字符相同的位置拿出來,把這些位置之間的串拿出來,判斷剩哪些子串合法即可。顯然是週期以外的都行。
注意,如果沒有任何相鄰位置的字符相同,我們需要計算這個環的週期,需要將環複製一次才行。
計算週期直接KMP即可。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}inline int get_s(char *s){
char c;while(isspace(c=gc())&&c!=EOF);if(c==EOF)return -1;
int len=0;while(s[len++]=c,!isspace(c=gc())&&c!=EOF);
s[len]='\0';return len;
}
char obuf[10000007],*oh=obuf;
struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;
}using namespace IO;
using std::cerr;
using std::cout;
cs int N=5e6+7;
int n;
char s[N<<1|1];
bool ans[N];int ps[N],ct;
int nx[N<<1|1];
void solve(char *a,int len){
for(int re i=2,j=0;i<=len;++i){
while(j&&a[i]!=a[j+1])j=nx[j];
if(a[i]==a[j+1])++j;nx[i]=j;
}int now=len,las=1;
while(now){
for(int re i=las;i<=len-nx[now];++i)if(n>i)ans[n-i]=true;
las=len-nx[now]+2;now=nx[now];
}
}
void Main(){
while((n=get_s(s+1))!=-1){
if(n==1){*oh++='0';*oh++='\n';continue;}
memset(ans,0,sizeof(bool)*n);
for(int re i=n+1;i<=2*n;++i)s[i]=s[i-n];
ct=0;for(int re i=1;i<=n;++i)if(s[i]==s[i+1])ps[++ct]=i;
if(ct)*oh++='0',ps[++ct]=ps[1]+n;else *oh++='1';
for(int re i=0;i<ct;++i)
solve(s+ps[i],ps[i+1]-ps[i]);
if(!ct)solve(s,n<<1);
for(int re i=1;i<n-1;++i)*oh++=ans[i]+'0';
*oh++='0';*oh++='\n';
}
}
inline void file(){
#ifndef ONLINE_JUDGE
freopen("loop.in","r",stdin);
freopen("loop.out","w",stdout);
#endif
}
signed main(){file();Main();return 0;}