Reverse and Rotate
题目描述
给定一个字符串 S S S 和 n n n 次操作,每次操作为以下 3 3 3 种形式之一:
-
< x
表示将 S S S 向左循环移动 x x x 位。例如: a b c d e \mathtt{abcde} abcde 执行< 2
后变成 c d e a b \mathtt{cdeab} cdeab。 -
> x
表示将 S S S 向右循环移动 x x x 位。例如: a b c d e \mathtt{abcde} abcde 执行> 2
后变成 d e a b c \mathtt{deabc} deabc。 -
rev
表示将 S S S 翻转。例如: a b c d e \mathtt{abcde} abcde 执行rev
后变成 e d c b a \mathtt{edcba} edcba。
求 S S S 在依次执行这 n n n 次操作后得到的字符串 S ′ S' S′。
注:对于 S = s 0 s 1 ⋯ s k − 1 S=s_0s_1\cdots s_{k-1} S=s0s1⋯sk−1,将其向左循环移动 x x x 位,会变成 s − x S − x + 1 ⋯ S − x + k − 1 s_{-x}S_{-x+1}\cdots S_{-x+k-1} s−xS−x+1⋯S−x+k−1;向右循环移动 x x x 位,会变成 s x S x + 1 ⋯ S x + k − 1 s_{x}S_{x+1}\cdots S_{x+k-1} sxSx+1⋯Sx+k−1。对于 x ≡ y ( m o d k ) x\equiv y\pmod k x≡y(modk),有 s x = s y s_x=s_y sx=sy。
输入格式
第一行一个字符串 S S S。
第二行一个整数 n n n。
接下来 n n n 行,每行一个操作。
输出格式
一行一个字符串 S ′ S' S′,表示依次执行 n n n 次操作后得到的字符串。
样例 #1
样例输入 #1
abcde
3
> 2
rev
< 2
样例输出 #1
aedcb
提示
【样例 1 解释】
- 原字符串为 a b c d e \mathtt{abcde} abcde;
- 第一次操作后,字符串变为 d e a b c \mathtt{deabc} deabc;
- 第二次操作后,字符串变为 c b a e d \mathtt{cbaed} cbaed;
- 第三次操作后,字符串变为 a e d c b \mathtt{aedcb} aedcb。
【数据规模与约定】
记 ∣ S ∣ |S| ∣S∣ 表示字符串 S S S 的长度。
测试点编号 | 特殊性质 |
---|---|
1 ∼ 3 1\sim3 1∼3 | ∣ S ∣ , n , x ≤ 1000 \vert S\vert,n,x \le 1000 ∣S∣,n,x≤1000 |
4 4 4 | 没有 rev 操作 |
5 5 5 | S = a a . . . a b b . . . b S=\mathtt{aa...abb...b} S=aa...abb...b |
6 ∼ 10 6\sim10 6∼10 | 无 |
对于 100 % 100\% 100% 的数据, 1 ≤ ∣ S ∣ , n ≤ 1 0 6 1 \le |S|,n \le 10^6 1≤∣S∣,n≤106, 0 ≤ x ≤ 1 0 9 0 \le x \le 10^9 0≤x≤109, S S S 仅由小写字母组成。
思路
- 首先,如果我们直接按照题目的要求去模拟(就是如下代码注释部分),只能得 30pts。
- 那我们怎么优化呢?对于这种移动的,有个累加效应(就是你往右移 2 个单位再往左移 2 个单位刚好抵消,因此就可以省去很大部分的暴力)
- 那这道题有翻转,我们该怎么解决呢?我们发现:如果字符串 abcde 需要右移 1 位。按正常顺序,先右移,变成 eabcd,再翻转,变成 dcbae。如果先翻转,
变成 edcba,发现只需要在左移 1 位,即右移 -1 位,就正好可以变为 dcbae。
因此我们的规律是,翻转前需右移 x 位,翻转后需右移 −x 位。
举个样例的例子:abcde - 原字符串为 a b c d e \mathtt{abcde} abcde;
- 第一次操作后,字符串变为 d e a b c \mathtt{deabc} deabc;
- 第二次操作后,字符串变为 c b a e d \mathtt{cbaed} cbaed;
- 第三次操作后,字符串变为
a
e
d
c
b
\mathtt{aedcb}
aedcb。
那么,我们可以先给字符串翻转: e d c b a \mathtt{edcba} edcba;
接着然后再向右移一位/向左移四位就变成 a e d c b \mathtt{aedcb} aedcb。
我们发现,我们如果不在翻转的地方修改一下就会导致我们计算结果错误,你看,如果我们不干预的话,2-2=0,然后再翻转,就会出问题,所以我们就得是-2-2=-4。
后面的就得是string 的substr的用法:
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
string a;
int n;
int s;
int k,r;//计算总的偏移
int main(){
cin>>a>>s;
n=a.size();
//暴力 30 pts
// while(s--){
// char p;
// cin>>p;
// int x;
// if(p=='>'){
// cin>>x;
// x%=n;
// int k=x;
// while(k--){
// char l=a[n-1];
// a.pop_back();
// a=l+a;
// }
// }else if(p=='<'){
// cin>>x;
// x%=n;
// int k=x;
// string t=a.substr(0,k);
// string c=a.substr(k);
// // cout<<c<<endl;
// a=c+t;
// }else{
// string pp;
// cin>>pp;
// reverse(a.begin(),a.end());
// }
// // cout<<a<<endl;
// }
while(s--){
char p;
cin>>p;
int x;
if(p=='>'){
cin>>x;
k+=(x%n);
}else if(p=='<'){
cin>>x;
k-=(x%n);
}else{
string pp;
cin>>pp;
r++;
k*=-1;
}
}
k%=n;
// cout<<k<<endl;
if(r&1){
reverse(a.begin(),a.end());
}
/*
如果字符串 abcde 需要右移 1 位。按正常顺序,先右移,变成 eabcd,再翻转,变成 dcbae。如果先翻转,
变成 edcba,发现只需要在左移 1 位,即右移 -1 位,就正好可以变为 dcbae。
因此我们的规律是,翻转前需右移 x 位,翻转后需右移 −x 位。
*/
if(k<0){
k=abs(k);
string t=a.substr(0,k);
string c=a.substr(k);
cout<<c<<t;
}else if(k>0){
// while(k--){
// char l=a[n-1];
// a.pop_back();
// a=l+a;
// }
cout<<a.substr(n-k)<<a.substr(0,n-k);
}
return 0;
}