参考题目:Shuffle’m Up
题目描述
还记得2020年招新赛中“编织字符串”这一道题吗?
tls在ac完以后想出了一个更有趣的问题,具体是这样的:
给定两个长度均为 len
的字符串 s1、s2
和一个长度为 len * 2
的字符串 s
,
每一次我们按照编织字符串的操作将 s1
和 s2
拼接起来,得到长度为 len * 2
的字符串 s'
然后令 s1
为 s'
的前一半,s2
为 s'
的后一半,反复以上操作。
若在某一次中 s'
和 s
相等则结束循环。
假设有 s1="JNU"
,s2="ACM"
,s="NAMJUC"
第一次操作后得到 s'="AJCNMU"
,与 s
不相等。
令 s1="AJC"
,s2="NMU"
第二次操作后得到 s'="NAMJUC"
,与 s
相等,结束循环。
输出操作次数为2
数据范围
1 ≤ l e n ≤ 100 1 \le len \le 100 1≤len≤100
运行效率
分析
模拟拼接情况,如果出现了循环并且没有找到答案,就说明无解。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define fi first
#define se second
using namespace std;
typedef pair<string, int> PSI;
// first 存字符串
// second 存变换步数
int n;
string s1, s2, s, t1, t2;
int bfs()
{
queue<PSI> q;
q.push({s, 1});
while (q.size())
{
PSI u = q.front(); q.pop();
string t;
for (int i = 0; i < n; i ++ )
t += s2[i], t += s1[i]; // 模拟拼接
if (t == s) return u.se; // 找到了返回步数
for (int i = 0; i < n; i ++ )
s1[i] = t[i];
for (int i = n; i < 2 * n; i ++ )
s2[i - n] = t[i];
if (t1 == s1 && t2 == s2) break; // 出现循环返回
q.push({t, u.se + 1});
}
return -1;
}
int main()
{
int T;
cin >> T;
for (int C = 1; C <= T; C ++ )
{
cin >> n;
cin >> s1 >> s2 >> s;
t1 = s1, t2 = s2;
cout << C << " " << bfs() << endl;
}
return 0;
}