题目链接
题意
给定字符串(s),可以在其中任意位置插入字符(x). 问能否得到一个回文串,若能,需插入多少个(x).
思路
首先统计出现次数为奇数的字符(cnt).
(cntgeq1)
显然无解
(cnt==1)
则回文串长度为奇数。找到中间位置,向两边check.
(cnt==0)
则回文串长度为偶数。找到中间的两个位置,向两边check.
// 很生气...打比赛时活生生将(n)跟在了(cnt)后面定义,于是用一个(char)类型的(n)去wa了一个小时,改写了好几版代码。
Code 1.
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long LL;
char s[maxn];
int cnt[256], n;
LL ans;
bool check(int i, int j) {
ans = 0;
for (; i>=0, j<n; ) {
if (s[i]==s[j]) {--i, ++j; continue; }
if (s[i]!='x'&&s[j]!='x') return 0;
if (s[i]=='x') ++ans, --i;
else if (s[j]=='x') ++ans, ++j;
}
if (i==-1) {
ans += n-j;
for (; j < n; ++j) if (s[j]!='x') {return 0; }
}
if (j==n) {
ans += i+1;
for (; i >= 0; --i) if (s[i]!='x') { return 0; }
}
return 1;
}
int main() {
scanf("%s", s);
n = strlen(s);
for (int i = 0; i < n; ++i) ++cnt[s[i]];
char ch;
int tot = 0, odd = 0;
for (int i = 'a'; i <= 'z'; ++i) {
if (i == 'x') continue;
if (cnt[i] & 1) ++odd;
tot += cnt[i];
}
if (odd > 1) { puts("-1"); return 0;}
if (tot == 0) { puts("0"); return 0; }
(tot /= 2) += 1;
int cur=0, i = 0, l=0, r=0;
for (; i < n; ++i) {
if (s[i] != 'x') ++cur;
if (cur == tot-1 && !r) r = i+1;
if (cur == tot) { l = i; break; }
}
if (odd) r = i, l = i+1;
if (check(r-1, l)) printf("%d
", ans);
else printf("-1
");
return 0;
}
Code 2.
#include <bits/stdc++.h>
#define maxn 500010
using namespace std;
typedef long long LL;
char s[maxn];
int cnt[256], n;
LL ans;
struct node {
char ch;
int cnt;
}a[maxn], b[maxn];
bool check(int i, int j) {
int cnt1 = 0, cnt2 = 0, tot1 = 0, tot2 = 0;
for (; i >= 0; --i) {
if (s[i] == 'x') ++cnt1;
else a[tot1++] = {s[i],cnt1}, cnt1 = 0;
}
for (; j < n; ++j) {
if (s[j] == 'x') ++cnt2;
else b[tot2++] = {s[j],cnt2}, cnt2 = 0;
}
if (tot1 != tot2) return false;
ans = 0;
for (int i = 0; i < tot1; ++i) {
if (a[i].ch != b[i].ch) return false;
ans += abs(a[i].cnt-b[i].cnt);
}
ans += abs(cnt1-cnt2);
return true;
}
int main() {
scanf("%s", s);
n = strlen(s);
for (int i = 0; i < n; ++i) ++cnt[s[i]];
char ch; int num=0;
for (char i = 'a'; i <= 'z'; ++i) if (i!='x'&&(cnt[i]&1)) ++num, ch = i;
if (num > 1) { printf("-1
"); return 0; }
int p;
if (num == 1) {
int hf = cnt[ch]/2+1, pst=0;
int i = 0;
for (; i < n; ++i) {
if (s[i] == ch && pst < hf) ++pst;
if (pst == hf) break;
}
if (check(i-1, i+1)) printf("%lld
", ans);
else printf("-1
");
}
else {
int tot = 0;
for (char i = 'a'; i <= 'z'; ++i) if (i!='x')tot += cnt[i];
if (tot==0) { puts("0"); return 0; }
tot /= 2;
int i = 0, pst = 0;
for (; i < n; ++i) {
if (s[i] != 'x' && pst < tot) ++pst;
if (pst == tot) break;
}
int p = i+1;
while (p<n && s[p]=='x') ++p;
if (check(i, p)) printf("%lld
", ans);
else printf("-1
");
}
return 0;
}