题意:
一个字符串s, 只由a, b, c三种字符构成,有m次询问,每次询问一个区间l, r,可以操作使l, r子串的某个字符改变,问需要的最少的次数使得,l, r区间之内的字符串,没有回文
思路:
题目说字符串只由三个字符构成,这个条件很特殊,然后通过观察发现,要构成回文串只能是abcabc, acbacb, 等,连续的三个字符必须是要不相等的,而且这就构成了上述的规律,abc的全排列有6中,分别讨论这6要变成这6中情况需要的消耗,答案就是6中答案里面的最小值
总结:
字符串的特殊性利用,循环节来构成无回文串的字符串,要求区间,只要区间相减,最后求min即可
点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;
int n, m;
string s;
int dp[6][MAXN];
int main()
{
IOS; cin.tie(0), cout.tie(0);
cin >> n >> m;
cin >> s;
string temps = "abc";
int pos = 0;
do
{
for (int i = 0; i < s.size(); ++i)
{
if (i % 3 == 0)
{
if (s[i] != temps[0])
dp[pos][i] = (i == 0) ? 1 : dp[pos][i - 1] + 1;
else
dp[pos][i] = (i == 0) ? 0 : dp[pos][i - 1];
}
else if (i % 3 == 1)
{
if (s[i] != temps[1])
dp[pos][i] = (i == 0) ? 1 : dp[pos][i - 1] + 1;
else
dp[pos][i] = (i == 0) ? 0 : dp[pos][i - 1];
}
else if (i % 3 == 2)
{
if (s[i] != temps[2])
dp[pos][i] = (i == 0) ? 1 : dp[pos][i - 1] + 1;
else
dp[pos][i] = (i == 0) ? 0 : dp[pos][i - 1];
}
}
++pos;
} while (next_permutation(temps.begin(), temps.end()));
while (m--)
{
int l, r;
cin >> l >> r;
l -= 1, r -= 1;
int ans = min({ dp[0][r] - dp[0][l - 1], dp[1][r] - dp[1][l - 1], dp[2][r] - dp[2][l - 1], dp[3][r] - dp[3][l - 1], dp[4][r] - dp[4][l - 1], dp[5][r] - dp[5][l - 1] });
cout << ans << endl;
}
return 0;
}
/*
1 1
baacb
2 3
*/