連結
有點意思的題目。
首先可以得到的一個結論就是,如果k能夠完成,那唯一的操作方法就是從前往後,遇到0就使用,把這個點變成1。
那麼我們就能夠做到O(n)驗證了,然後發現O(n^2)可以接受,就過了。
但是我因為濫用資料結構,導致我認為驗證需要O(nlogn)然後5000又剛剛好跑不過去。
所以覺得做法假了,嘗試從減少驗證的次數上下手。
首先可以發現一個性質,就是如果k=m的時候是可以分解完成的,那麼m的所有因子作為k也是可以的,
那假如能夠證明,所有合法的k都是一個數字的因子的話,那這題就可以透過質因數分解的方法來做到兩個log
很明顯,不可以。反例:011110 k=5和2都可以。
然後就做法假了。
死因:沒有發現滑動視窗是不需要動態維護字首和的,只需要O(1)即可維護。
這一點記下來,以後還是儘量少用樹狀陣列吧。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int dp[2000501];//注意陣列大小
char str[2000501],s[2000501];
int odd[2000501],even[2000501];
int len,N;
bool cherk(int l,int r)
{
int mid=l+r>>1;
if((r-l+1)%2==0)
{
if(odd[mid]>=(r-l+1))return 1;
else return 0;
}
else
{
if(even[mid]>=(r-l+1))return 1;
else return 0;
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int T=read();char c1;
for(int t=1;t<=T;t++)
{
for(int i=0;i<=N;i++)
{
// str[i]=s[i]=0;
dp[i]=0;
odd[i]=even[i]=0;
}
for(int i=0;i<=N+2;i++)str[i]=0;
N=0,len=0;
scanf("%s",s+1);
if(t==1)c1=s[1];
int N=0,len=strlen(s+1);
bool flag=0;dp[1]=dp[0]=0;
for(int i=2;i<=len;i++)
{
if(len%2==1&&(i==(1+len>>1)))continue;
if(s[i]!=s[1])flag=1;
}
if(s[1]!=s[len])flag=1;
if(flag==0)
{
cout<<"No"<<endl;
continue;
}
for(int i=1;i<=len;i++)
{
dp[i]=0;
}
str[0]='$';//防止越界
for(int i=1;i<=len;i++)
{
str[++N]='#';
str[++N]=s[i];
}
str[++N]='#',str[++N]='@';//最後再加一個@
int right=0,pos=0;
for(int i=1;i<=N;i++)dp[i]=0;
for(int i=1;i<=N;i++){
if(i<right)
dp[i]=min(dp[2*pos-i],right-i);
else
dp[right=i]=1;
while(str[i-dp[i]]==str[i+dp[i]])
dp[i]++;
if(i+dp[i]>right)
right=i+dp[i],pos=i;
}
int ret=0;
for(int i=1;i<=N;i++)
ret=max(ret,dp[i]-1);//找最長迴文
for(int i=1;i<=N;i++)
{
if(i%2==1)
{
odd[i/2]=dp[i]-1;
}
else
{
even[i/2]=dp[i]-1;
}
}
if(ret!=len)
{
cout<<"Yes"<<endl;
cout<<1<<endl;
for(int i=1;i<=len;i++)
{
cout<<s[i];
}
cout<<endl;
continue;
}
flag=0;
for(int i=2;i<len;i++)
{
if(s[i+1]!=s[i-1])flag=1;
}
if(flag==0)
{
cout<<"No"<<endl;
continue;
}
int mid=0;
for(int i=2;i<len;i++)
{
if(cherk(1,i)==0&&cherk(i+1,len)==0)
{
mid=i;
break;
}
}
if(mid==0)
{
cout<<"No"<<endl;
continue;
}
cout<<"Yes"<<endl;
cout<<2<<endl;
// }
for(int i=1;i<=mid;i++)
{
cout<<s[i];
}
cout<<' ';
for(int i=mid+1;i<=len;i++)
{
cout<<s[i];
}
cout<<endl;
}
return 0;
}
/*
1
aabaaabaa
aababaa
1
aaabaaa
*/