bzoj 3916: friends 瞎搞

题目:

有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S.

题解:

发现字符串的长度一定为奇数.
然后发现问题变成了
\(s[0 .. mid]\)\(s[mid+1 .. len]\)仅删除的编辑距离为1
或 : \(s[0 .. mid-1]\)\(s[mid .. len]\)仅删除的编辑距离为1

然后我们可以联想到以前的:电子词典
所以我们这道题可以直接暴力dfs查找..

不要忘记特判下标不同但本质相同的字符串.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
	x=0;char ch;bool flag = false;
	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 2000010;
char s[maxn];int ans,n,pos,del;
bool end_all1,end_all2;
void dfs1(int i,int j,bool f,int d){
	if(end_all1) return;
	if(i == pos+1){
		del = d;
			end_all1 = true; 
		++ ans;
		return;
	}
	if(s[i] != s[j] || j == n){
		if(f) dfs1(i+1,j,false,i);
		else return;
	}else{
		dfs1(i+1,j+1,f,d);
		if(f) dfs1(i+1,j,false,i);
	}
}
void dfs2(int i,int j,bool f,int d){
	if(end_all2) return;
	if(i == n){
		del = d;
		end_all2 = true; 
		++ ans;
		return;
	}
	if(s[i] != s[j] || j == pos){
		if(f) dfs2(i+1,j,false,i);
		else return;
	}else{
		dfs2(i+1,j+1,f,d);
		if(f && i != pos) dfs2(i+1,j,false,i);
	}
}
int main(){
	read(n);
	if(n % 2 == 0 || n == 1) return puts("NOT POSSIBLE");
	pos = (n>>1);scanf("%s",s);
	dfs1(0,pos+1,true,0);
	if(s[pos] == s[0]) dfs2(pos+1,1,true,0);
	if(ans == 2){
		int i;
		for(i=0;i<pos && s[i] == s[pos+i+1];++i);
		if(i < pos) puts("NOT UNIQUE");
		else for(int i=0;i<pos;++i) putchar(s[i]);
	}
	else if(ans == 0) puts("NOT POSSIBLE");
	else{
		if(del < pos){
			for(int i=0;i<=pos;++i){
				if(del == i) continue;
				putchar(s[i]);
			}
		}else{
			for(int i=pos;i<n;++i){
				if(del == i) continue;
				putchar(s[i]);
			}
		}
		puts("");
	}
	getchar();getchar();
	return 0;
}
posted @ 2017-03-17 21:28  Sky_miner  阅读(182)  评论(0编辑  收藏  举报