首页 > 试题广场 >

小红的字符串

[编程题]小红的字符串
  • 热度指数:2357 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}小红拥有一个长度为 n 的小写字母字符串 s。她可以重复执行如下操作任意次:
\hspace{23pt}\bullet\, 选择一个下标 i\ (1\leqq i\leqq n),将字符 s_i 循环右移到字母表中的下一个字母。特别地,``\texttt{z}`` 右移后变成 ``\texttt{a}``。
\hspace{15pt}
\hspace{15pt}请计算,使 s 变为回文串所需的最少操作次数。

\hspace{15pt}【名词解释】回文串:一个字符串从左往右与从右往左读完全相同。

输入描述:
\hspace{15pt}一行输入一个长度不超过 1000 的小写字母字符串 s


输出描述:
\,\,\,\,\,\,\,\,\,\,在一行上输出一个整数,代表把 s 变成回文串的最少操作次数。
示例1

输入

abcd

输出

4

说明

一种可行方案:\texttt{(共 4 次操作)。
示例2

输入

nuhhhh

输出

19
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        int len = s.length();
        int sum = 0;
        
        for (int i = 0; i < len / 2; i++) {
            char a = s.charAt(i);
            char b = s.charAt(len - 1 - i);
            
            // 计算两个字符的最小距离(循环右移次数)
            int diff = Math.abs(a - b);
            sum += Math.min(diff, 26 - diff);
        }
        
        System.out.println(sum);
    }
}
    

发表于 2025-09-03 14:30:53 回复(0)
word = input().strip()

def dif(a,b):
    dif1 = abs(ord(a) - ord(b))
    return min(dif1,26-dif1)

nword = len(word)
out = 0
for i in range(nword):
    if i < nword-i-1:
        out = out + dif(word[i],word[nword-i-1])
    else:
        break
print(out)

发表于 2025-08-15 12:46:30 回复(0)
#include <ios>
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    string s;
    cin>>s;
    int cnt=0;
    int i=0,j=s.size()-1;
    while(i<j){
        cnt+=min(abs(s[i]-s[j]),26-abs(s[i]-s[j]));
        i++,j--;
    }
    cout<<cnt;

    return 0;
}
// 64 位输出请用 printf("%lld")
发表于 2025-07-05 16:50:17 回复(0)
#include <iostream>
using namespace std;

int main() {
    // 将字符串从中间分开
    string str;
    while (cin >> str) {
        int subStrSize = str.size() / 2;
        string leftSubStr = str.substr(0,subStrSize);
        string rightSubStr = str.substr(subStrSize,subStrSize);
        int cnt = 0;
        for (int i = 0; i < subStrSize; i++) {
            char tmpLeftStr = leftSubStr[i];
            char tmpRightStr = rightSubStr[subStrSize-1-i];
            if (tmpLeftStr != tmpRightStr) {
                // 先让左边字符循环右移,在让右边字符循环右移,比较哪个操作次数少
                int leftNum = 0;
                while (tmpLeftStr != tmpRightStr) {
                    if (tmpLeftStr == 'z') {
                        tmpLeftStr = 'a';
                    } else {
                        tmpLeftStr += 1;
                    }
                    leftNum++;
                }
                //
                tmpLeftStr = leftSubStr[i];
                tmpRightStr = rightSubStr[subStrSize-1-i];
                int rightNum = 0;
                while (tmpLeftStr != tmpRightStr) {
                    if (tmpRightStr == 'z') {
                        tmpRightStr = 'a';
                    } else {
                        tmpRightStr += 1;
                    }
                    rightNum++;
                }
                cnt += leftNum < rightNum ? leftNum : rightNum;
            }
        }
        cout << cnt << endl;
    }
}

发表于 2025-12-12 14:50:09 回复(0)
#include <iostream>
#include <iterator>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

int main() {
    string s;
    cin>>s;
    vector<char> v1;
    vector<char> v2;
    for(int i=0;i<s.size();i++)
    {
        v1.push_back(s[i]);
    }
    v2=v1;
    reverse(v2.begin(),v2.end());
    int n=0;
    for(int i=0;i<(v1.size()/2);i++)
    {
        if(abs(v1[i]-v2[i])<=26-abs(v1[i]-v2[i]))
        {
            n+=abs(v1[i]-v2[i]);
        }
        else n+=26-abs(v1[i]-v2[i]);
    }
    cout<<n;
}
// 64 位输出请用 printf("%lld")
发表于 2025-12-07 23:12:29 回复(0)
#include <iostream>
#include <string>

int func(char a,char b)
{
    int res = std::min((b-a+26)%26,(a-b+26)%26);
    return res;
}

int main()
{
    std::string s;
    std::cin>>s;

    int n = s.size();
    int ans = 0;
    for(int l = 0,r = n-1;l<r;l+=1,r-=1)
    {
        ans += std::min(func(s[l],s[r]),func(s[r],s[l]));
    }

    std::cout<<ans<<'\n';
}

发表于 2025-11-29 18:43:32 回复(0)
#include <any>
#include <iostream>
using namespace std;

int main() {
    string s;
    cin >> s;
    int sum = 0;
    for(int i = 0, j = s.length() - 1; i < j; i++, j--){
        if(s[i] > s[j]) swap(s[i], s[j]);
        if(s[j] - s[i] <= 13) sum += (s[j] - s[i]);
        else sum += (26 - (s[j] - s[i]));
    }
    cout << sum << endl;
    return 0;
}
// 64 位输出请用 printf("%lld")
/*
a -- b 1步
b -- a 26步
s[cur] - s[tar] <= 13; 步骤增加 s[tar] - s[cur]
s[cur] - s[tar] > 13; 步骤增加 26 - (star - s[cur]);
a b c d e f g h i j k l m 
n o p q r s t u v w x y z
*/
abs函数和min函数互相配合维护累计器同样可以,这里就不贴了

发表于 2025-10-24 19:11:56 回复(0)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    function minOperationsToPalindrome(s) {
        const n = s.length;
        let count = 0;

        for (let i = 0; i < Math.floor(n / 2); i++) {
            const left = s.charCodeAt(i) - 97; // 'a' -> 0
            const right = s.charCodeAt(n - 1 - i) - 97;

            const diff = Math.abs(left - right);
            count += Math.min(diff, 26 - diff);
        }

        return count;
    }

    while ((line = await readline())) {
        console.log(minOperationsToPalindrome(line));
    }
})();

发表于 2025-10-06 18:53:12 回复(0)
#include <stdio.h>
#include <string.h>

int main() {
    //没刷过题真不懂用贪心算法。循环右移原来指的是单个字母+1变成下一个字母不是位置移动
    //贪心的过程就是判断左边移动多点还是右边移动多点,贪最少的那一边就行,看来不难
    int a, b;
    char string[1000];
    scanf("%s",string);
    int l=strlen(string);
    //printf("%c",string[l-1]);

    int buzhou=0;//统计要走多少步
    for(int i=0;i<l-1-i;i++)
    {
        int j=l-1-i;  //尾部的字母
        //比较两边哪边花的步数少
        if(string[i]<string[j])
        {
            int temp1=string[j]-string[i]; //正常右移的步数
            int temp2='z'-string[j]+(string[i]-'a')+1;   //大的那个右移是否更小

            //选更小的加,贪心
            if(temp1<temp2)
            {
                buzhou+=temp1;
            }else {
                buzhou+=temp2;
            }
        }else if(string[i]>string[j]){
            int temp1=string[i]-string[j]; //正常右移的步数
            int temp2='z'-string[i]+(string[j]-'a')+1;   //大的那个右移是否更小

            //选更小的加,贪心
            if(temp1<temp2)
            {
                buzhou+=temp1;
            }else {
                buzhou+=temp2;
            }
        }else {  //相等就不管
            continue;
        }
    }

    printf("%d",buzhou);
   
    return 0;
}
发表于 2025-10-03 11:50:54 回复(0)
s=input()
b=0
for i in range(len(s)//2):
    b+=min(abs(ord(s[i])-ord(s[-(i+1)])),26-abs(ord(s[i])-ord(s[-(i+1)])))
print(b)
发表于 2025-09-11 17:54:30 回复(0)
import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) throws IOException {
        String str = br.readLine();
        int strlen = str.length();
        int sum = 0;
        // a ok 0
        // ab 0,1 1
        // abc 0,2/1,1 2
        // abcd 0,3/1,2/2,2 4
        for (int i = 0; i < strlen / 2; i++) {
            sum += cal(str.charAt(i), str.charAt(strlen - i - 1));
        }
        System.out.println(sum);
    }

    public static int cal (char a, char b) {
        // a z 25 1
        int len = Math.abs(a - b);
        int minlen = Math.min(len, 26 - len);
        if (minlen == 0) return 0;
        return minlen;
    }

    static BufferedReader br = new BufferedReader(new InputStreamReader(
                System.in)); //br.readLine() 读字符串
    static StreamTokenizer st = new StreamTokenizer(br);
    static int ad() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }
}

发表于 2025-09-08 16:28:00 回复(0)
s = input()
len_s = len(s)
answer = 0
for i in range(len_s//2):
    dis = abs(ord(s[i])-ord(s[len_s-i-1]))
    answer += min(dis,26-dis)
print(answer)
发表于 2025-09-07 00:25:45 回复(0)
import java.util.*;
import java.io.*;

//下标为i和下标为n-1-i的字符是一组c1和c2。
//c1操作和c2操作一个右移到另一个是最短的,
//两个都移动为第三个字符的情况一定会比单个移动到另一个的移动次数多,因为可假设第三字符在两个字符之间或两字符之外循环单向移动都会更长

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        char[] input=bf.readLine().toCharArray();
        int min=0;
        for(int a=0,b=input.length-1;a<b;a++,b--){
            int c1c2=(input[a]-input[b]+26)%26;//c1右移到c2  取模为正取正,为负取正向移动的另一半距离。
            int c2c1=(input[b]-input[a]+26)%26;//c2右移到c1
            min+=Math.min(c2c1,c1c2);
        }
        System.out.println(min);
    }
}

发表于 2025-09-03 12:42:04 回复(0)
都差不多一样的思想,不过我算步骤用的是取模(顺时针的走)
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl '\n'
#define N 100005

string s;
int ans=0;

int check(char st,char end){
    return ((int)end-(int)st+26)%26;
}
signed main() {
    cin>>s;
    for(int i=0;i<s.size()/2;i++){
        ans+=min(check(s[i],s[s.size()-1-i]),check(s[s.size()-1-i],s[i]));
    }
    cout<<ans<<endl;
    return 0;
}
// 64 位输出请用 printf("%lld")

发表于 2025-08-24 11:35:47 回复(0)
#include <stdio.h>
#include <string.h>

int main() {
    char str[1001];
    scanf("%s", str);
    int n = strlen(str);
    int count = 0;

    for (int left = 0, right = n - 1; left < right; left++, right--) {
        if (str[left] != str[right]) {
            int forward = (str[right] - str[left] + 26) % 26;
            int backward = (str[left] - str[right] + 26) % 26;
            count += (forward < backward)?forward:backward;
        }
    }
    printf("%d", count);
    return 0;
}
发表于 2025-07-11 20:32:48 回复(0)
a = list(map(str,input().strip()))
b = []
len_a = len(a)
left = 0
right = len_a - 1
sum = 0
x = 0
y = 0
for i in range(len_a):
    x = abs(ord(a[left]) - ord(a[right]))
    y = 26 - abs(ord(a[left]) - ord(a[right]))
    sum += min(x,y)
    left +=1
    right -=1
    if left >= right:
        break
print(sum)
发表于 2025-06-21 20:04:09 回复(0)