friends's 题解

这,是一道很神奇的题目

因为它乱搞也能过。。。

甩出一个链接,自己看题面吧:https://www.lydsy.com/JudgeOnline/problem.php?id=3916

好的,明显想字符串hash对不对?但很显然这个我不熟,怎么办?打算骗分试试(于是就乱搞出正解了

首先,它是由一个字符串复制后在某个位置加上一个字母产生的,所以它输入的 n n n 一定是一个大于1的奇数,如果不是,直接输出 “ N O T “NOT NOT P O S S I B L E ” POSSIBLE” POSSIBLE 结束(这步为了防止毒瘤数据,虽然并没有)。

然后考虑,由于是两个相同的字符串中间加了一个字母来的,所以分三种情况:字母加在左边的字符串中,字母加在右边的字符串中以及一种特判情况(加在左串或右串的末尾,这种特判情况最后讨论,因为我第一遍就是这个没考虑清楚wa了。)

所以把原字符串以 m i d mid mid 为界可以分成 1 1 1 m i d mid mid m i d + 1 mid+1 mid+1 n n n 两个串或者 1 1 1 m i d − 1 mid-1 mid1 m i d mid mid n n n 两个串,用两个指针过一遍检验,如果搜到第一组不同的,较长字符串的指针加一并且把 f l fl fl 标记为1,然后再测如果还有不同的,把 f l fl fl 标记为-1后break,上面两种情况同时进行,如果两个 f l fl fl 均为-1,输出 “ N O T “NOT NOT P O S S I B L E ” POSSIBLE” POSSIBLE,如果一个为-1一个为1,说明只有一种情况成立,输出 f l fl fl 为1的那组里较小的字符串。

好了来说一下特殊情况,因为我自己太菜的原因,如果较长串最后一位是多出来的话,这位是没办法扫到的,所以只能进行特判,明显如果是你最后一位是加上去的话,你的 f l fl fl 还是没有变成1或者-1的,应该为0。

在第一种情况中,最后一位在 m i d mid mid 的位置,另一个 f l fl fl 的判断中,这个字母由于是在长串的开头,一定已经被扫到过了(除非是只由相同单个字母组成的,那很明显这时输出也一样),即使旁边有字母和它一样,但效果是一样的,直接输出右串即可。

在第二种情况中,最后一位在 n n n 的位置,另一个 f l fl fl 有两种情况,如果 n n n 位置和 1 1 1 以及 m i d mid mid 位置上的字母不一样,那么显然另一个 f l fl fl 会变成-1,只能删去 n n n 位置上的才能成立;如果 n n n 位置和 1 1 1 以及 m i d mid mid 位置上的字母一样,那么它一定会被扫到(由相同单个字母组成的情况已经在上一种中包含了所以不用考虑了),但此时明显你删掉 n n n 位置和 1 1 1 位置都是成立的,所以要输出 “ N O T “NOT NOT U N I Q U E ” UNIQUE” UNIQUE(或者像我代码中一样判断 f l fl fl 为-1输出左串,另外不多的情况就是最后总输出的 “ N O T “NOT NOT U N I Q U E ” UNIQUE” UNIQUE )。

最后的输出可以合并简化的但明显我懒得简化因为这样会容易理解一点(也为了防止出错)。

(上一个恶心的代码帮助理解)

#include<bits/stdc++.h>
using namespace std;
#define fi(a) freopen(a,"r",stdin)
#define fo(a) freopen(a,"w",stdout)
#define sfd(n) scanf("%d",&n)
#define sfs(n) scanf("%s",n+1)
#define f1(i,l,r) for(int i=l;i<=r;++i)
#define pfc(n) printf("%c",n)
const int N=2e6+10;
int n,mid,sum=0,fl1=0,fl2=0;
char u[N];
void freo(){fi("t2.in"); fo("t2.out");}
void init(){sfd(n); if(!(n&1)||n==1){printf("NOT POSSIBLE"); exit(0);} sfs(u);}
void work(){
    mid=n/2+1;
    for(int l=1,r=mid+1;r<=n;++l,++r){
        if(!fl1&&u[l]!=u[r]) ++l,fl1=1;
        if(u[l]!=u[r]){fl1=-1; break;}
    }
    for(int l=1,r=mid;l<=mid-1;++l,++r){
        if(!fl2&&u[l]!=u[r]) ++r,fl2=1;
        if(u[l]!=u[r]){fl2=-1; break;}
    }
}
void prin(){
    if(fl1==-1&&fl2==-1) printf("NOT POSSIBLE");
    else if(fl1==1&&fl2==-1) f1(i,mid+1,n) pfc(u[i]);
    else if(fl2==1&&fl1==-1) f1(i,1,mid-1) pfc(u[i]);
    else if(fl1==0) f1(i,mid+1,n) pfc(u[i]);
    else if(fl2==0&&fl1==-1) f1(i,1,mid-1) pfc(u[i]);
    else printf("NOT UNIQUE");
}
int main(){freo(); init(); work(); prin(); return 0;}

不过还是建议写一下hash的熟悉一下,毕竟这样讨论很容易漏掉某种情况。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值