题解 CF1109B Sasha and One More Name

先考虑Impossible的情况。

显然如果所有字符全一样那肯定无解。

还有一种情况就是 \(n\) 为奇数且除了中间的一个字符其余全部相等,也无解。

理由很简单,剩下的字符全相等,由于新串是回文的,所以和原来的串一定是同一个串。

下面我们分奇偶性来讨论。

  • \(n\) 为奇数

这种情况下,答案不大于 \(2\) ,因为除了中间的旁边的字符不全相等,所以一定有中间的一段,他的两边不是回文串,直接切两下就行了。

同时,答案也不可能小于 \(2\) ,因为如果一刀就行的话,由于新串回文,且长度为奇数,所以手动模拟一下就能看出,这样一定所有字符都相等才能让新串和原串全都回文,而这时答案为Impossible,不符合题意。

所以当 \(n\) 为奇数时,答案为 \(2\)

  • \(n\) 为偶数

这时稍微麻烦一点,分两种情况。

我们取串的前一半,由于是回文长度为偶数的串,所以后一半一样的不用管就可以了。

  1. 取出的这个串不是回文串,这时直接一刀把原串从中间分成两段即可,答案为 \(1\)
  2. 取出的串是回文串,这样我们可以把整个原串分成两半,因为这一半回文,所以求出当串长为 \(\frac{n}{2}\) 时的答案。如果是 \(2\) 就对称的切一刀,原串答案仍为 \(2\) 。如果是 \(1\) 就还在那个位置切,原串答案仍为 \(1\) 。所以新串的答案即为原串的答案,递归处理即可。

时间复杂度 \(O(n\log n)\)

代码

#include<bits/stdc++.h>
#define re register
#define N 1001001
#define MAX 2001
#define inf 1e18
using namespace std;
typedef long long ll;
typedef double db;
inline void read(re ll &ret)
{
    ret=0;re ll pd=0;re char c=getchar();
    while(!isdigit(c)){pd|=c=='-';c=getchar();}
    while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();}
    ret=pd?-ret:ret;
    return;
}
ll t,n;
char s[N];
signed main()
{
    t=1;
    while(t--)
    {
        scanf("%s",s+1);
        n=strlen(s+1);
        re bool flag=true;
        for(re int i=2;i<=(n>>1);i++)
            flag&=(s[i]==s[i-1]);
        if(flag)
        {
            puts("Impossible");
            continue;
        }
start:
        flag=true;
        for(re int i=1;(i<<1)<=n;i++)
        {
            if(s[(n>>1)-i+1]!=s[i])
                flag=false;
        }
        if(!flag&&(n&1))
        {
            puts("2");
            continue;
        }
        else if(!flag&&!(n&1))
        {
            puts("1");
            continue;
        }
        else if(flag&&(n&1))
        {
            puts("2");
            continue;
        }
        else if(flag&&!(n&1))
        {
            n>>=1;
            goto start;//即为前文所说的递归,goto简化代码
        }
 
    }
	exit(0);
}
posted @ 2020-10-17 20:14  CelticOIer  阅读(147)  评论(6编辑  收藏  举报