题解 字符消除2
首先证一个结论:t集合即是原串的boarder不用证了吧
于是转化题意:要构造一个boarder集合确定的01串
考虑从小的boarder推向大的boarder,令小boarder为s,大boarder为t
- \(|s|*2 \leqslant |t|\) 此时在s后面补上s的一段后缀即可
- \(|s|*2 > |t|\) 把原串复制一遍接在最后,其它位置全补0
kmp check一下它有没有多出来新的boarder,如果有就把补的最后一个0换成1
证明见这里
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
#define ull unsigned long long
//#define int long long
int n;
char s[N];
ull h[N], p[N];
const ull base=131;
inline ull hashing(ull* h, int l, int r) {return h[r]-h[l-1]*p[r-l+1];}
namespace force{
int t[2000], top;
ull h2[2010];
void solve() {
//cout<<"solve "<<n<<endl;
top=0;
for (int i=1; i<=n; ++i) h[i]=h[i-1]*base+s[i];
for (int i=1; i<=n; ++i) {
ull m=hashing(h, 1, i);
int j;
for (j=i+1; j+i-1<=n; j+=i)
if (hashing(h, j, j+i-1)!=m) goto jump;
if (j<=n && hashing(h, 1, n-j+1)!=hashing(h, j, n)) goto jump;
t[++top]=i;
jump: ;
}
//cout<<"top: "<<top<<endl;
//for (int i=1; i<=top; ++i) cout<<t[i]<<' '; cout<<endl;
int lim=1<<n;
for (int s=0; s<lim; ++s) {
//cout<<"now s="<<bitset<6>(s)<<endl;
int pos=1;
for (int i=1; i<=n; ++i) h2[i]=h2[i-1]*base+(s&(1<<(i-1))?1:0);
for (int i=1; i<=n; ++i) {
ull m=hashing(h2, 1, i);
int j;
for (j=i+1; j+i-1<=n; j+=i)
if (hashing(h2, j, j+i-1)!=m) goto jump2;
if (j<=n && hashing(h2, 1, n-j+1)!=hashing(h2, j, n)) goto jump2;
//cout<<"cmp: "<<i<<' '<<t[pos]<<endl;
if (i==t[pos]) ++pos;
else break;
jump2: ;
}
if (pos==top+1) {
for (int i=n-1; ~i; --i) printf("%d", s&(1<<i)?1:0); printf("\n");
break;
}
}
}
}
namespace task{
int nxt[N], t[N], top, siz;
char ans[N];
void solve() {
top=0;
nxt[1]=0;
for (int i=2,j=0; i<=n; ++i) {
while (j && s[i]!=s[j+1]) j=nxt[j];
if (s[i]==s[j+1]) ++j;
nxt[i]=j;
}
int it=n;
do {t[++top]=it; it=nxt[it];} while (it) ;
//cout<<"nxt: "; for (int i=1; i<=top; ++i) cout<<t[i]<<' '; cout<<endl;
siz=0;
if (t[top]==1) ans[++siz]=0;
else {
while (t[top]>1) ans[++siz]=0, --t[top];
ans[++siz]=1;
}
for (int i=top-1; i; --i) {
//cout<<"i: "<<i<<' '<<siz<<endl;
//cout<<"ans: "; for (int i=1; i<=siz; ++i) printf("%d", ans[i]); printf("\n");
if (siz*2>=t[i])
for (int j=siz-(t[i]-siz)+1,ends=siz; j<=ends; ++j) ans[++siz]=ans[j];
else {
//cout<<"pos1"<<endl;
int dlt=t[i]-siz+1;
for (int j=siz+1; j<dlt; ++j) ans[j]=0;
for (int j=dlt; j<=t[i]; ++j) ans[j]=ans[j-dlt+1];
nxt[1]=0;
for (int k=2,j=0; k<=t[i]; ++k) {
while (j && ans[k]!=ans[j+1]) j=nxt[j];
if (ans[k]==ans[j+1]) ++j;
nxt[k]=j;
}
if (nxt[t[i]]!=siz) ans[dlt-1]=1;
siz=t[i];
}
}
for (int i=1; i<=siz; ++i) printf("%d", ans[i]); printf("\n");
}
}
signed main()
{
int T;
//cout<<double(sizeof(h)*3)/1024/1024<<endl;
p[0]=1;
for (int i=1; i<=2000; ++i) p[i]=p[i-1]*base;
scanf("%d", &T);
while (T--) {
scanf("%s", s+1);
n=strlen(s+1);
//force::solve();
task::solve();
}
return 0;
}