Reverse and Rotate(字符串(STL用法)+模拟+思维+找规律)

108 篇文章 0 订阅

Reverse and Rotate

题目描述

给定一个字符串 S S S n n n 次操作,每次操作为以下 3 3 3 种形式之一:

  1. < x 表示将 S S S 向左循环移动 x x x 位。例如: a b c d e \mathtt{abcde} abcde 执行 < 2 后变成 c d e a b \mathtt{cdeab} cdeab

  2. > x 表示将 S S S 向右循环移动 x x x 位。例如: a b c d e \mathtt{abcde} abcde 执行 > 2 后变成 d e a b c \mathtt{deabc} deabc

  3. 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=s0s1sk1,将其向左循环移动 x x x 位,会变成 s − x S − x + 1 ⋯ S − x + k − 1 s_{-x}S_{-x+1}\cdots S_{-x+k-1} sxSx+1Sx+k1;向右循环移动 x x x 位,会变成 s x S x + 1 ⋯ S x + k − 1 s_{x}S_{x+1}\cdots S_{x+k-1} sxSx+1Sx+k1。对于 x ≡ y ( m o d k ) x\equiv y\pmod k xy(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 13 ∣ S ∣ , n , x ≤ 1000 \vert S\vert,n,x \le 1000 S,n,x1000
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 610

对于 100 % 100\% 100% 的数据, 1 ≤ ∣ S ∣ , n ≤ 1 0 6 1 \le |S|,n \le 10^6 1S,n106 0 ≤ x ≤ 1 0 9 0 \le x \le 10^9 0x109 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值