所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i+1個字元交換,使得該串最終變為回文串。求最少交換次數。
乙個由大寫字母字母組成的字串。
若能經過有限次操作能將原串變為回文串,則輸出最少操作次數;否則輸出-1。
輸入輸出樣例
輸入
shllzshzs
輸出4
說明/提示
樣例說明
交換 l 和 z 變成 shlzlshzs
交換 l 和 z 變成 shzllshzs
交換 l 和 s 變成 shzlslhzs
交換 h 和 z 變成 shzlslzhs
資料範圍
\(40\%\) 的資料, 長度\(\leq50000\)
\(100\%\) 的資料, 長度\(\leq10^6\)
貪心,逆序對貪心策略:每次選擇最靠外邊的字元作為回文串的一部分
證明(摘自 tsreaper ):
構造回文串的過程,實際上是每次選擇一對字母並把它們交換到字串頭尾的過程。考慮字母 \(x\) 和字母 \(y\) 哪 個先選,分以下情況討論:
// %%%skyqwq
#include //#define int long long
#define help
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
typedef pairpii;
typedef pairpll;
template bool chkmax(t &x, t y)
template bool chkmin(t &x, t y)
template void inline read(t &x)
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}const int n=1e6+5;
string s;
int n,res[n],b[n],c[n];
vectora[26];
bool v[n];
void add(int x,int y)
int ask(int x)
int main()
int f=0;
for(int i=0;i<26;i++)
if(a[i].size()&1)f++;
if(n%2==0&&f||n%2==1&&f!=1)puts("-1");
else
}int l=1,r=n,pos=1;
while(pos<=n)
if(pos>n||l>r)break;
v[pos]=true;
res[l++]=pos++;
int t=a[b[pos-1]][a[b[pos-1]].size()-1];
v[t]=true;
res[r--]=t;
a[b[pos-1]].pop_back();
} }ll ret=0;
for(int i=n;i;i--)ret+=ask(res[i]),add(res[i],1);
cout
}
洛谷P5041 HAOI2009 求回文串
傳送門 題目描述 所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i 1個字元交換,使得該串最終變為回文串。求最少交換次數。輸入格式 乙個由大寫字母字母組成的字串。輸出格式 若能經過有限次操作能...
haoi2009 求回文串
所謂回文串,就是對於給定的字串,正著讀和反著讀都一樣,比如abcba就是乙個回文串,abcab則不是。我們的目標是對於任意輸入的字串,不斷將第i個字元和第i 1個字元交換,使得該串最終變為回文串。求最少交換次數。題解 有一種做法是貪心 就是每次找到最左端的字元,然後找到這序列中最右邊的一樣的字元,然...
P2513 HAOI2009 逆序對數列
題目描述 對於乙個數列,如果有iaj,那麼我們稱ai與aj為一對逆序對數。若對於任意乙個由1 n自然數組成的數列,可以很容易求出有多少個逆序對數。那麼逆序對數為k的這樣自然數數列到底有多少個?錯誤日誌 沒想対,菜是原罪,最近狀態不佳 在一段 1 i 1 的排列中加入 i 你可以控制 i 插入的位置,...