洛谷P7814 「小窝 R3」心の記憶

题意#

第一行给定两个数字n m (mn)分别代表给定字符串长度以及需要构造出的字符串长度
第二行给定一个长度为n的字符串 (假设原来的字符串是a 需要构造出来的字符串是 x)
构造出的字符串需要满足 子序列与子串的定义
1.x的任意一个子串都与a不相同
2.x的某一个子序列和a相同

分析#

  • n=1的时候,显然无法存在x满足条件
  • n=2的时候,如果两个字符串中的字符不同,显然构造不出
  • n=m的时候,显然满足条件2的时候,xy是一模一样的,无法满足条件1

假设现在以上三种情况均不可能发生

  • 我们可以找到每个与 他的下一个字符相同的字符,然后在这样一对字符中间加入一个与他们不相同的字符
  • 如果找不到在第一个字符(除了最后一个的任意一个字符均可)后面输出与它不相同的字符即可

AC_CODE#

#define pb push_back
#include <bits/stdc++.h>
#define rep(i, b, s) for(int i = (b); i <= (s); ++i)

using namespace std;
void solve() {
    int n, m; scanf("%d%d", &n, &m);
    string a; cin >> a;
    // 三种不可能构造出的情况
    if(n == 1 || n == m || n == 2 && a[0] != a[1]) {
        puts("-1");
        return;
    }
    //构造方式为找到每个与 他的下一个字符相同的字符,然后在这样一对字符中间加入一个与他们不相同的字符 
    // 如果找不到在第一个字符(除了最后一个的任意一个字符均可)后面输出与它不相同的字符即可


    //寻找出 每个与 他的下一个字符相同的字符 存起来
    vector<int> v;
    for(int i = 0; a[i + 1]; i ++) 
        if(a[i] == a[i + 1]) {
            v.pb(i);
        }
    int len = v.size();

    if(!len) { // 找不到的情况
        putchar(a[0]);
        for(int i = 0; i < m - n; i ++ ) putchar(a[0] ^ 1);
        rep(i, 1, n - 1) putchar(a[i]);
        puts("");
        return;
    }

    int p = 0;
    int ans = m - n;
    for(int i = 0; a[i]; i ++ ) { // 找到了这样的字符
        putchar(a[i]);
        if(i == v[p] && ans) {
            putchar(a[i] ^ 1);
            p ++; ans --;
            if(p == len) {
                rep(j, 1, ans) putchar(a[i] ^ 1);
                ans = 0;
            }
        }
    } 
    puts("");    
}

signed main() 
{
    int T = 1;cin >> T;
    while(T -- ) solve();
    return 0;
}
posted @   ccz9729  阅读(62)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩