题目大意:

As a token of his gratitude, Takahashi has decided to give Snuke a level-KK palindrome. A level-LL palindrome, where LL is a non-negative integer, is defined as follows:

  • Let rev(s)rev(s) denote the reversal of a string ss.
  • A string ss is said to be a palindrome when s=rev(s)s=rev(s).
  • The empty string and a string that is not a palindrome are level-00 palindromes.
  • For any non-empty level-(L−1)(L−1) palindrome tt, the concatenation of t,rev(t)t,rev(t) in this order is a level-LL palindrome.
  • For any level-(L−1)(L−1) palindrome tt and any character cc, the concatenation of t,c,rev(t)t,c,rev(t) in this order is a level-LL palindrome.

Now, Takahashi has a string SS. Determine whether it is possible to make SS an exactly level-KK palindrome by doing the following action zero or more times: choose a character in SS and change it to another lowercase English letter. If it is possible, find the minimum number of changes needed to make SS a level-KK palindrome.

(自己翻译去)

题目思路:

粗略分析:

通过“最少改变”这个关键词,我们不难想到贪心算法。

对于本道题,我们的贪心策略是:
找到字母相同的位置,用桶统计这个集合中每个字母出现的次数。

找到出现最多和次多的字母及最多出现的个数,

并将集合中的字母全部变成出现最多的那个字母,

同时统计答案。

问题细化:

Q1:如何找到必须相同的字母的位置?

A:使用分治算法,并用并查集来维护这个集合(并查集在替换操作上还有用处)

Q2:impossible情况

①k太大(大概是k>=20)

②len=pow(2,k)

③len<pow(2,k-1)

Q3:特殊判断!

1)替换后的字符串有更深层的回文。

这个时候记录下的次多的字母个数就有用处了。只需要掉一个非后回文串中心的字母就可以了。(要比较找最优方法)

并查集的性质也可以保证每个集合的总祖先是连续的处于字符串的头部的。非常方便进行替换操作。

2)特判:长度唯一的字符串回文深度为1

code:

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int k;
string s;
int ans=0;
int b[N][30];//桶
int maxn[N];//最大
int emaxn[N];//次大
int bel[N];//最小的子字符串中的字母
int f[N];//并查集
vector<int> res;//存最小子字符串的下标 int find(int x)//找祖先
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
} void h(int x,int y)//认祖先
{
f[find(x)]=find(y);
return ;
} void dfs(int l,int r,int lev){//二分
if(lev==k) return ;
int len=(r-l+1);
if(len%2==1){
dfs(l,l+len/2-1,lev+1);dfs(l+len/2+1,r,lev+1);
}
if(len%2==0){
dfs(l,l+len/2-1,lev+1);dfs(l+len/2,r,lev+1);
}int mid=(l+r)/2;//奇回文串和偶回文串需要分开讨论
for(int i=0;r-i>=mid;i++) h(r-i,l+i);//建立集合
return ;
} bool judge(int len){//判断是否为回文串
for(int i=1;i<=len;i++) if(bel[i]!=bel[len-i+1]){return true;}
return false;
} int main(){
cin>>k>>s;
int len=s.size();
s=" "+s;
if(k>=20||len/(1<<k)==1||len<(1<<(k-1))){puts("impossible");return 0;}//无解的判断 for(int i=1;i<=len;i++) f[i]=i;//并查集初始化 int dip=k;
int anslen=len;//anslen表示最小子串的长度 while(dip--){
anslen/=2;//计算最小子串的长度
} dfs(1,len,0);//二分
for(int i=1;i<=len;i++){
b[find(i)][s[i]-'a']++;
if(find(i)==i) res.push_back(i);//res存的是一个完整的最小子串
} int sum=res.size(); for(int i=0;i<sum;i++){
int x=res[i];
for(int j=0;j<26;j++){
if(b[x][j]>maxn[x]) {emaxn[x]=maxn[x];maxn[x]=b[x][j];bel[x]=j;}
else emaxn[x]=max(emaxn[x],b[x][j]);//找最大和找次大
}
} for(int i=0;i<sum;i++) ans+=maxn[res[i]];//统计ans if(!anslen){cout<<len-ans;return 0;}//最小子串长度为1的特判
if(!judge(anslen)){//包含更深的回文
int minn=12345678;
for(int i=1;i<=anslen;i++){
if(anslen%2==1&&i==anslen/2+1) continue;
minn=min(minn,maxn[i]-emaxn[i]);//寻找最佳替换方案
}
ans-=minn;
}
cout<<len-ans;
return 0;
}

E - Level K Palindrome的更多相关文章

  1. 【LeetCode】1400. 构造 K 个回文字符串 Construct K Palindrome Strings

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 统计奇数字符出现次数 日期 题目地址:https:// ...

  2. uva 122 trees on the level——yhx

    题目如下:Given a sequence of binary trees, you are to write a program that prints a level-order traversa ...

  3. 链表之求链表倒数第k个节点

    题目描述:输入一个单向链表,输出该链表中倒数第k个节点,链表的倒数第0个节点为链表的尾指针. 最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点.注意链表为空,k为0,k为1,k大 ...

  4. E - Trees on the level

     Trees on the level  Background Trees are fundamental in many branches of computer science. Current ...

  5. 1101-Trees on the Level

    描述 Trees are fundamental in many branches of computer science. Current state-of-the art parallel com ...

  6. 设计一个算法,求非空二叉树中指定的第k层(k&gt;1)的叶子节点的个数

    思想:採用基于层序遍历的方法. 用level扫描各层节点,若某一层的节点出队后.rear指向该层中最右节点.则将rear赋值给last(对于第一层.last=1).在出队时,若front=last,表 ...

  7. UVA122-Trees on the level(链二叉树)

    Trees on the level Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Sub ...

  8. Trees on the level(指针法和非指针法构造二叉树)

    Trees on the level Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  9. hdu 1622 Trees on the level(二叉树的层次遍历)

    题目链接:https://vjudge.net/contest/209862#problem/B 题目大意: Trees on the level Time Limit: 2000/1000 MS ( ...

随机推荐

  1. 阻塞队列——四组API

    方式 抛出异常 有返回值,不抛出异常 阻塞等待 超时等待 添加 add() offer() put() offer(...) 移除 remove() poll() take() poll(...) 检 ...

  2. Python函数注解

    目录 函数注解概述 实际应用 inspect模块 业务代码 总结 以下内容基于Python 3x 涉及的知识前提: 建议理解Python装饰器后学习此内容 函数注解概述 函数注解可以针对函数的参数.返 ...

  3. Go benchmark 一清二楚

    前言 基准测试(benchmark)是 go testing 库提供的,用来度量程序性能,算法优劣的利器. 在日常生活中,我们使用速度 m/s(单位时间内物体移动的距离)大小来衡量一辆跑车的性能,同理 ...

  4. 一文让你对js的原型与原型链不再害怕、迷惑

    目录 原型与原型链的详细剖析 原型 显式原型prototype 隐式原型__proto__ 显式原型prototype与隐式原型__proto__的关系 原型链(隐式原型链) 探寻原型链的尽头 完整详 ...

  5. Jenkins+Python自动化测试持续集成详细教程

    ​ Jenkins是一个开源的软件项目,是基于java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能.由于是基于java开发因此它也依赖jav ...

  6. Redis单机数据库的实现原理

    本文主要介绍Redis的数据库结构,Redis两种持久化的原理:RDB持久化.AOF持久化,以及Redis事件分类及执行原理.最后,分别介绍了单机班Redid客户端和Redis服务器的使用和实现原理. ...

  7. redis过期key监听事件

    目录 redis安装 docker拉取 启动 redis 配置 命令监听 问题 程序监听 具体监听类 效果 总结 redis常用语缓存操作,但是redis功能不仅仅于此.今天我们来看看redis的ke ...

  8. Solon 框架详解(九)- 渲染控制之定制统一的接口输出

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  9. P1089_津津的储蓄计划(JAVA语言)

    package 顺序与分支; /* * 题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱, 津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄, ...

  10. Linux+mysql混杂

    一.linux 1.linux中给某一文件中批量新增一个内容 先vim进入文件,然后先按ctrl+v 然后选中需要的行数, 在shift+i 写你要添加的东西 然后在按下esc 二,mysql 1.l ...