小红的回文串
[题目链接](https://www.nowcoder.com/practice/f63e9827b5e349179becdce3bd3be8ca)
思路
本题有两种操作:把首字符移到末尾(旋转)和将任意字符改为任意字母。目标是用最少的总操作次数把字符串变成回文串。
枚举旋转次数
操作一本质上是对字符串做左旋转。旋转 次后,原串
变为
。
对于旋转后的字符串,要将其变成回文串,只需数有多少对位置 上的字符不同,每对不同只需一次操作二即可修复。
因此,枚举旋转次数 (从
到
),总操作次数为:
$$
答案即为 。
样例演示
对 :
:串为
aacde,不匹配对,cost =
:串为
acdea,不匹配对,cost =
:串为
cdeaa,不匹配对,cost =
- ...
最小值为 ,与预期一致。
复杂度分析
- 时间复杂度:
,外层枚举
种旋转,内层检查
对字符。
- 空间复杂度:
,只需存储输入字符串。
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
string s;
cin >> s;
int ans = n;
for(int k = 0; k < n; k++){
int changes = 0;
for(int i = 0; i < n/2; i++){
int li = (k + i) % n;
int ri = (k + n - 1 - i) % n;
if(s[li] != s[ri]) changes++;
}
ans = min(ans, k + changes);
}
cout << ans << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String s = sc.next();
int ans = n;
for (int k = 0; k < n; k++) {
int changes = 0;
for (int i = 0; i < n / 2; i++) {
int li = (k + i) % n;
int ri = (k + n - 1 - i) % n;
if (s.charAt(li) != s.charAt(ri)) changes++;
}
ans = Math.min(ans, k + changes);
}
System.out.println(ans);
}
}
import sys
input = sys.stdin.readline
n = int(input())
s = input().strip()
ans = n
for k in range(n):
changes = 0
for i in range(n // 2):
li = (k + i) % n
ri = (k + n - 1 - i) % n
if s[li] != s[ri]:
changes += 1
ans = min(ans, k + changes)
print(ans)
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
const lines = [];
rl.on('line', line => lines.push(line.trim()));
rl.on('close', () => {
const n = parseInt(lines[0]);
const s = lines[1];
let ans = n;
for (let k = 0; k < n; k++) {
let changes = 0;
for (let i = 0; i < Math.floor(n / 2); i++) {
const li = (k + i) % n;
const ri = (k + n - 1 - i) % n;
if (s[li] !== s[ri]) changes++;
}
ans = Math.min(ans, k + changes);
}
console.log(ans);
});

京公网安备 11010502036488号