Evil Straw Warts Live (Uva10716 回文串+贪心)

【原题】

A palindrome is a string of symbols that is equal to itself when reversed. Given an input string, not necessarily a palindrome, compute the number of swaps necessary to transform the string into a palindrome. By swap we
mean reversing the order of two adjacent symbols. For example, the string "mamad" may be transformed into the palindrome "madam" with 3 swaps:

  • swap "ad" to yield "mamda"
  • swap "md" to yield "madma"
  • swap "ma" to yield "madam"

The first line of input gives n, the number of test cases. For each test case, one line of input follows, containing a string of up to 100 lowercase letters. Output consists of one line per test case. This line will contain the number of swaps, or
"Impossible" if it is not possible to transform the input to a palindrome.

【Sample Input】

3
mamad
asflkj
aabb

【Output for Sample Input】

3
Impossible
2

题意:判断一个串能否通过临近的两个字符多次交换变成回文串,不能输出“Impossible”,能的话输出最少的交换次数。

思路:预处理每个字母出现的次数,若有>=2个字母出现的次数是奇数则不可能。然后从两边向中间贪心,每次先固定前端,然后从后端向中间逐步找,直到找到第一个与前端相同字母时break,将找到的字母向后移,加上移动的次数(不知道为什么可以这么做,网上说这样做 和 每次找最优 最后结果是一样的,暂时还没有证明出来)。若碰到个数为奇数的字母时,将它往后顺移,最后它就会在中央位置了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 8005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

char str[maxn];
int num[28];
bool vis[maxn];

int main()
{
    int n,i,j;
    sf(n);
    while (n--)
    {
        mem(num,0);
        scanf("%s",str);
        int len=strlen(str);
        FRL(i,0,len)
            num[str[i]-'a']++;
        int ans=0;
        FRL(i,0,26)
            if (num[i]%2) ans++;
        if (ans>1)
        {
            pf("Impossible\n");
            continue;
        }
        ans=0;
        int L=0,R=len-1;
        while (L<len/2)
        {
            int j=R;
            while (j>L)
            {
                if (str[L]==str[j])
                    break;
                j--;
            }
            if (j==L)   //找到了应该放在中间的字母,将它往后顺移
            {
                char ch=str[L];
                str[L]=str[L+1];
                str[L+1]=ch;
                ans++;
            }
            else
            {
                ans+=(R-j);
                FRL(i,j,R)
                    str[i]=str[i+1];
                R--;
                L++;
            }
        }
        pf("%d\n",ans);
    }
    return 0;
}
时间: 2024-08-27 00:49:04

Evil Straw Warts Live (Uva10716 回文串+贪心)的相关文章

uva--10716Evil Straw Warts Live +回文串+贪心

题意: 输入一个字符串,我们可以交换这个字符串中的相邻字符:问至少经过多少步交换可以得到一个回文串:如果无论怎么交换都得不到回文串,输出"Impossible": 思路: 首先由回文串的定义和性质,可以得到两种不可能情况:1.当这个串长度为奇数时,如果出现次数为奇数次字母的数目不为1,则显然不可能.2.当这个串长度为偶数时,如果出现次数为奇数次字母的个数大于0,则不可能. 除去这两种不可能的情况后,这个串就一定可以转成回文串.我们只需要考虑0--len/2(len为串长)的部分,对于第

UVA10716 - Evil Straw Warts Live

题意:如果可以的话,使用最少的交换次数,使得字符串变成回文字符串. 思路: 1.首先我们可以先判断这个字符串是否有成为回文的可能性.当一个字符串中出现两个或两个以上的奇数个数的字符,那么这个字符串一定不能成为回文字符串. 2.之后就要讨论怎么使用最少的交换次数使得变成回文字符串.我们可以采取由外到内的方法,即先将头尾两端的字符交换成相同的,然后left++,right--,慢慢向内靠拢. 为了让交换次数最少,那么每次移动到左右两个端点的字符的交换次数也要最少.这样的话就要找相同字符第一次出现和最

UVA - 10716 - Evil Straw Warts Live (简单模拟)

UVA - 10716 Evil Straw Warts Live Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Evil Straw Warts Live A palindrome is a string of symbols that is equal to itself when reversed. Given an

最少回文串--牛客网(秋招备战专场三模)-C++方向

题目描述:一个字符串从左向右和从右向左读都完全一样则是回文串,给定一个字符串,问该字符串中的字符所能组成的最少的回文串的个数为多少 解题思路:如果一个字符出现的次数为偶数,则必能组成回文串,如果一个字符出现奇数次,只能自己组成回文串,题目中问最少的回文串数目,即求出现次数为奇数次的字符个数即可,定义a存储每个字符出现的次数,统计出现奇数次的字符的个数,即为输出 1 #include <iostream> 2 #include <string> 3 using namespace s

回文串问题

1.回文串的判断 #include <iostream> #include <string.h> using namespace std; //回文串的判断 bool isPalindrome(const char* src) { if(src == NULL) return true; int end = strlen(src)-1,begin = 0; while(begin < end)//从两边向中间判断,当然也可以从中间向两边判断 { if(src[begin] !

bzoj 2565: 最长双回文串

Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同).输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串. Input 一行由小写英文字母组成的字符串S. Output 一行一个整数,表示最长双回文子串的长度. Sample Input baacaabbacabb Sample Output 12 HINT

BZOJ2565:最长双回文串

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2195  Solved: 1119[Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都

Power oj/2610[判断回文串]

题目链接[https://www.oj.swust.edu.cn/problem/show/2610] 题意:给你一个字符串,让你判断这个字符串是不是回文串,字符串的长度是1<len<1e7,内存是4096KB. 题解:首先这1e7个字符是存不下的,1e71024=9765KB>4096kB.那么怎么办?字符串哈希,先对字符串的前半部分进行哈希,然后在对字符串后半部分进行哈希,如果两部分的哈希值相同,那么这个字符串就是回文串. BKDRH哈希,哈希公式为has=has*seed+s[i]

409.求最长回文串的长度 LongestPalindrome

题目要求求出长度即可,并不需要求出最长回文串. 思路:用字典统计每一个字符的出现次数,出现次数大于1的字符必定出现在回文串中,另外还再加上一个中心点. public static int LongestPalindrome(string s) { int length = 0; Dictionary<char, int> dictionary = new Dictionary<char, int>(); int value = 0; foreach (char c in s) {