E. Decypher the String
题意:
有一个字符串,一些操作,每次操作交换两个位置的字符,经过这些操作后,会得到新的字符串。给你新的字符串,求原来的串。可以有3次询问,每次询问给出一个字符串,返回操作后的字符串。
分析:
如果长度小于等于26,那么询问abc...xyz,就可以知道每个位置操作后的对应的位置。那么长度大于26的时候,考虑均分成26段,每段是一个字符,然后可以知道每段对应的位置集合。继续在每一段内均分即可,均分3次,即可到单个位置。
代码实现很有意思,写成一个26进制数。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> #include<bitset> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 10005; char s[N], s1[N], s2[N], s3[N], ans[N]; bitset<N> a1[27], a2[27], a3[27], now; int pos[N]; int main() { scanf("%s",s); int n = strlen(s); for (int i = 0; i< n; ++i) { int t = i; s1[i] = 'a' + t % 26; t /= 26; s2[i] = 'a' + t % 26; t /= 26; s3[i] = 'a' + t % 26; t /= 26; } printf("? "); puts(s1); fflush(stdout); scanf("%s", s1); printf("? "); puts(s2); fflush(stdout); scanf("%s", s2); printf("? "); puts(s3); fflush(stdout); scanf("%s", s3); for (int i = 0; i < n; ++i) a1[s1[i] - 'a'].set(i); for (int i = 0; i < n; ++i) a2[s2[i] - 'a'].set(i); for (int i = 0; i < n; ++i) a3[s3[i] - 'a'].set(i); for (int i = 0; i < n; ++i) { int t = i; now = a1[t % 26]; t /= 26; now &= a2[t % 26]; t /= 26; now &= a3[t % 26]; t /= 26; for (int j = 0; j < n; ++j) if (now[j]) { pos[i] = j; break; } } for (int i = 0; i < n; ++i) ans[i] = s[pos[i]]; printf("! %s ", ans); return 0; }