2532 前缀和后缀
小b有一个长度为
的只含小写字母的字符串S,她求出了S的长度分别为
的
个前
缀和长度分别为
的
个后缀。
现在她告诉你这2n-2个字符串(并不告诉你哪些是前缀哪些是后缀),但她可能说谎,即改变
某些字符串的某些字符(注意不可能改变长度)。
请问小b说的有没有可能是真的?即是否存在串S使得小b给出的串能和串S的长度为
的
前后缀一一对应。
输入
第一行一个正整数n,2<=n<=100。 接下来2n-2行,每行一个字符串。输出
如果小b说的可能是真的,输出"Possible"; 否则输出"Impossible"。输入样例
2 a c输出样例
Possible
题意:
最后一句话是题意。
思路:
PS:题目其实是保证长度合法的,所以不需要特殊判断。
自己的思路是排序后看第一个字符串属于前缀还是后缀,然后按顺序分情况讨论下去,
100多行。。。,其实我是在很暴力的正向模拟整个过程,缺点是每次匹配完后,参与匹配
的两个串都将发生变化,模拟过程巨复杂。
更好的思路是将两个最长的串拼接(两种方式,分别作为前缀和后缀),即逆向考虑,
然后遍历所有的其他字串(两两一组),看是不是能和最长串发生匹配。这样只需要固定
两个拼接好的串然后遍历判断其他串即可,过程简化了许多。
第二种思路题解的代码:
#include <bits/stdc++.h>
using namespace std;
const int maxN = 200;
struct ch {
int a;
string b;
};
int n;
ch ss[maxN + 5];
string c;
bool cmp(ch A, ch B) {
return A.a < B.a;
}
string s1, s2;
int m;
bool checkpre(string x,string y) {
for(int i=0; i<y.size(); i++)
if(x[i]!=y[i]) return 0;
return 1;
}
bool checksuf(string x,string y) {
int ptr = y.size()-1;
for(int i=x.size()-1; i>=x.size()-y.size(); i--)
if(x[i]!=y[ptr--]) return 0;
return 1;
}
bool check(string x) {
for(int i = 0; i < m ; i += 2) {
if(checkpre(x,ss[i].b)&&checksuf(x,ss[i+1].b)) continue;
if(checksuf(x,ss[i].b)&&checkpre(x,ss[i+1].b)) continue;
return 0;
}
return true;
}
int main () {
cin >> n;
m = 2 * n - 2;
for(int i = 0; i < m; i++) {
cin >> c;
ss[i].b = c;
ss[i].a = c.length();
}
sort(ss,ss + m,cmp);
s1 = ss[m - 1].b + ss[m - 2].b;
s2 = ss[m - 2].b + ss[m - 1].b;
if(!check(s1)) {
if(!check(s2)) cout << "Impossible" << endl;
else cout << "Possible" << endl;
} else cout << "Possible" << endl;
return 0;
}
第一思路:自己的巨复杂的模拟+无数分支判断:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<set>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e5+100;
const int M=4e5+100;
string str[N];
bool cmp(string aa,string bb)
{
return aa.length()<bb.length();
}
int vis[N];
int main()
{
int n,flag=0;
cin>>n;
for(int i=1; i<=2*n-2; i++)
{
cin>>str[i];
}
sort(str+1,str+n*2-1,cmp);
int cnt=1;
for(int i=1; i<=2*n-2; i+=2)
{
if(str[i].length()==str[i+1].length()&&str[i].length()==cnt++)
{
continue;
}
else
{
cout<<"Impossible"<<endl;
return 0;
}
}
if(n==2)
{
cout<<"Possible"<<endl;
return 0;
}
//2*n-2>=4
// for(int i=1;i<=2*n-2;i++){
// cout<<i<<":"<<str[i]<<"..."<<endl;
// }
if(str[1]+str[3][1]==str[3])
{
vis[3]=1;
vis[1]=1;
cnt=3;
int p=3;
for(int i=3; i<=2*n-4; i+=2)
{
if(str[p]+str[i+3][cnt-1]==str[i+3])
{
vis[i+3]=1;
p=i+3;
}
else if(str[p]+str[i+2][cnt-1]==str[i+2])
{
vis[i+2]=1;
p=i+2;
}
else
{
//cout<<i<<":"<<str[i]<<" "<<str[i+2]<<" "<<str[i+3]<<endl;
cout<<"Impossible"<<endl;
return 0;
}
cnt++;
}
}
else if(str[1]+str[4][1]==str[4])
{
cnt=3;
vis[4]=1;
vis[1]=1;
int p=4;
for(int i=4; i<=2*n-4; i+=2)
{
if(str[p]+str[i+1][cnt-1]==str[i+1])
{
vis[i+1]=1;
p=i+1;
}
else if(str[p]+str[i+2][cnt-1]==str[i+2])
{
vis[i+2]=1;
p=i+2;
}
else
{
cout<<"Impossible"<<endl;
return 0;
}
cnt++;
}
}
else if(str[3][0]+str[1]==str[3])
{
vis[3]=2;
vis[1]=2;
int p=3;
for(int i=3; i<=2*n-4; i+=2)
{
if(str[i+3][0]+str[p]==str[i+3])
{
vis[i+3]=2;
p=i+3;
}
else if(str[i+2][0]+str[p]==str[i+2])
{
vis[i+2]=2;
p=i+2;
}
else
{
cout<<"Impossible"<<endl;
return 0;
}
}
}
else if(str[4][0]+str[1]==str[4])
{
vis[4]=2;
vis[1]=2;
int p=4;
for(int i=4; i<=2*n-4; i+=2)
{
if(str[i+1][0]+str[p]==str[i+1])
{
vis[i+1]=2;
p=i+1;
}
else if(str[i+2][0]+str[p]==str[i+2])
{
vis[i+2]=2;
p=i+2;
}
else
{
cout<<"Impossible"<<endl;
return 0;
}
}
}
else
{
cout<<"Impossible"<<endl;
return 0;
}
string s=str[2];
if(vis[1]==1)
{
for(int i=3; i<=2*n-2; i++)
{
if(vis[i]==0)
{
if(str[i][0]+s==str[i])s=str[i];
else
{
cout<<"Impossible"<<endl;
return 0;
}
}
}
}
else
{
cnt=2;
for(int i=3; i<=2*n-2; i++)
{
if(vis[i]==0)
{
if(s+str[i][cnt-1]==str[i])s=str[i];
else
{
cout<<"Impossible"<<endl;
return 0;
}
cnt++;
}
}
}
cout<<"Possible"<<endl;
return 0;
}
THE END;