题目链接:http://oj.daimayuan.top/course/10/problem/678
dls 桌面上的两个小女孩除了喜欢亲亲以外,还喜欢一起共用一副耳机听歌。
一天,她们正在听她们最喜欢的歌,一首歌的歌词可以看着一个只包含小写字母的字符串,保证字符串的长度为偶数。
不幸的是,她们的 eirpods 是拼夕夕九块九包邮的,发生了一些神奇的故障,使得对于每个字母,恰好只有一个人能够听到。
在一首歌放完后,她们一边抱怨耳机的质量,同时惊奇地发现,她们两个人所听到的字母各自组成的字符串完全相同。
给定一首歌的歌词,判断这种事情是否可能发生。
形式化题意:给定一个长度是偶数,仅有小写字母构成的字符串,判断是否能被分成两个完全相同的子序列。
输入格式
第一行一个正整数 TT,表示数据组数。
接下来每一行一个字符串 SS,表示歌词。
输出格式
输出共 TT 行,每行一个字符串 possible
或 impossible
,表示该组数据的答案。
样例输入
- 5
- aabb
- abba
- namonamo
- arqmpfvvbtltlhufznkldkurrazmgebfxeamrewn
- aacfcfqqsmksimkoioeertbrtbhphnpnggddjjll
样例输出
- possible
- impossible
- possible
- impossible
- possible
思路:如果对整个字符串爆搜的话,每次有两个选择,40个字符串,复杂度为2^40显然超时
那么我们就把他分成两半进行折半搜索,这样复杂度降为2^20大约是1e6,这样就不会超时
那么我们分别搜前半段和后半段,对每个字符要么给a要么给b
然后搜完前后两段之后我们在查一下前面半段的a+后面半段的a==前面半段的b+后面半段的b
例如:
那么我们可以知道前半段的前缀相等,后半段的后缀相等,前半段多出来的和后半段多出来的中间段相等
那么我们可以对于每次前半段搜到的a,b,先判断前缀是否相等
如果相等,就把中间多出来的用set存一下
然后对于后半段每次搜出来的a,b,先判断他的后缀是否相等
如果相等的话我们就把他的中间段拿出来看看set里有没有,如果有的话就说明符合s1==s2了
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- typedef pair<int,int> pii;
- int gcd(int a,int b) {
- return b? gcd(b,a%b):a;
- }
- /*
- int dx[8]={-2,-2,-1,1,2,2,-1,1};
- int dy[8]={-1,1,2,2,1,-1,-2,-2};
- int dx[4]={0,-1,0,1};
- int dy[4]={-1,0,1,0};
- int dx[8]={-1,1,0,0,-1,-1,1,1};
- int dy[8]={0,0,-1,1,-1,1,-1,1};
- */
- //int e[N],ne[N],h[N],idx,w[N];
- /*void add(int a,int b,int c){
- e[idx]=b;
- w[idx]=c;
- ne[idx]=h[a];
- h[a]=idx++;
- }
- */
- const int N=2e5+10;
- int n;
- bool f;
- set<string> ss;
- string s;
- void dfs1(int st,int end,string &a,string &b){
- if(f)return ;
- if(st>end){
- for(int i=0;i<min(a.size(),b.size());i++){
- if(a[i]!=b[i])return ;
- }
- if(a.size()<b.size()){
- ss.insert(b.substr(a.size()));
- }else {
- ss.insert(a.substr(b.size()));
- }
- return ;
- }
- a.push_back(s[st]);
- dfs1(st+1,end,a,b);
- a.pop_back();
- b.push_back(s[st]);
- dfs1(st+1,end,a,b);
- b.pop_back();
- }
- void dfs2(int st,int end,string a,string b){
- if(f)return ;
- if(st>end){
- reverse(a.begin(),a.end());
- reverse(b.begin(),b.end());
- for(int i=0;i<min(a.size(),b.size());i++){
- if(a[i]!=b[i])return ;
- }
- string op;
- if(a.size()<b.size()){
- op=b.substr(a.size());
- }else op=a.substr(b.size());
- reverse(op.begin(),op.end());
- if(ss.count(op) ){
- f=true;
-
- }
- return ;
- }
- a.push_back(s[st]);
- dfs2(st+1,end,a,b);
- a.pop_back();
- b.push_back(s[st]);
- dfs2(st+1,end,a,b);
- b.pop_back();
- }
- void sove(){
- s.clear();
- ss.clear() ;
- cin>>s;
- f=false;
- n=s.size();
- s="?"+s;
- string a,b;
- dfs1(1,n/2,a,b);
- dfs2(n/2+1,n,a,b);
- if(f)cout<<"possible"<<endl;
- else cout<<"impossible"<<endl;
- }
-
- signed main(){
- ios::sync_with_stdio(false);
- cin.tie() ,cout.tie() ;
- int t;
- cin>>t;
- while(t--){
- sove();
- }
- return 0;
- }