首页 > 其他分享 >YC302A [ 20240617 CQYC省选模拟赛 T1 ] 构造字符串(string)

YC302A [ 20240617 CQYC省选模拟赛 T1 ] 构造字符串(string)

时间:2024-06-17 18:21:27浏览次数:10  
标签:YC302A string 省选 text back int isl push include

题意

你需要构造一个长度为 \(n\) 的字符串。

使得后缀数组为给定的序列 \(a\),\(\text{manacher}\) 的回文序列为 \(b\)。

Sol

注意到后缀数组实际上是一系列 \(\le\) 的限制,而 \(\text{manacher}\) 是一堆相等以及两个不相等的限制。

若直接建边很难搞。

考虑将限制统一,后缀数组不好动,可以考虑将 \(\text{manacher}\) 的限制当成 \(\le\) 做。

平凡的,按照后缀数组的字典序一位一位确定。

思考 \(j\) 什么时候不能与字典序的前一个 \(i\) 取等。

\(S_i, S_{i + 1}, ... S_{n}\)

\(S_j, S_{j + 1}, ... S_{n}\)

显然,设 \(S_i = S_j\),则比较 \(S_{i + 1}, ... S_{n}\) 与 \(S_{j + 1}, .. S_{n}\) 的字典序大小。

乍一看我们无法确定 \(S_{i + 1}\) 与 \(S_{j + 1}\) 的字典序。

但是这个东西不显然等价于 \(i + 1\) 与 \(j + 1\) 在后缀数组的排名大小吗?

剩下地,对于 \(\text{manacher}\) 提供的不等限制,直接扔进桶里,每次清空即可。

不难发现,如果我们尽量放相同的,正好满足了 \(\text{manacher}\) 的限制。

最后直接用 \(\text{manacher}\) 跑一遍,判掉不合法情况即可。

Code

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#include <queue>
#include <vector>
#include <bitset>
#include <assert.h>
using namespace std;
#ifdef ONLINE_JUDGE

#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf;

#endif
int read() {
    int p = 0, flg = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') flg = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        p = p * 10 + c - '0';
        c = getchar();
    }
    return p * flg;
}
void write(int x) {
    if (x < 0) {
        x = -x;
        putchar('-');
    }
    if (x > 9) {
        write(x / 10);
    }
    putchar(x % 10 + '0');
}
bool _stmer;

const int N = 2e6 + 5;

array <vector <int>, N> isl;
array <int, N> s, p, h;

bitset <N> vis;
queue <int> q;

void clear() {
    while (!q.empty())
        vis[q.front()] = 0, q.pop();
}

array <int, N> arc;

void solve() {
    int n = read();
    for (int i = 1; i <= n; i++) {
        s[i] = read() + 1;
        p[s[i]] = i, isl[i].clear();
    }
    arc.fill(0);
    for (int i = 1; i <= 2 * n - 1; i++) {
        h[i] = read();
        int len = h[i] / 2;
        if (i & 1) {
            int tp1 = (i + 1) / 2 - len - 1, tp2 = (i + 2) / 2 + len + 1;
            if (tp1 < 1 || tp2 > n) continue;
            isl[tp1].push_back(tp2), isl[tp2].push_back(tp1);
        }
        else {
            int tp1 = (i / 2) - len, tp2 = (i / 2) + len + 1;
            if (tp1 < 1 || tp2 > n) continue;
            isl[tp1].push_back(tp2), isl[tp2].push_back(tp1);
        }
    }
    p[n + 1] = 0;
    int res = 'a';
    string ans(n, ' ');
    clear();
    for (int i = 1; i <= n; i++) {
        if (i != 1 && (vis[s[i]] || p[s[i] + 1] < p[s[i - 1] + 1])) clear(), res++;
        if (res > 'z') return (void)puts("-1");
        ans[s[i] - 1] = res;
        for (auto k : isl[s[i]])
            vis[k] = 1, q.push(k);
    }
    string tp; tp.push_back('~');
    for (auto k : ans) tp.push_back('|'), tp.push_back(k);
    tp.push_back('|');
    int mid = 0, r = 0;
    for (int i = 1; i <= 2 * n; i++) {
        if (i <= r) arc[i] = min(r - i + 1, arc[2 * mid - i]);
        while (tp[i - arc[i]] == tp[i + arc[i]]) arc[i]++, assert(i - arc[i] >= 0);
        if (i + arc[i] > r) r = arc[i] + i - 1, mid = i;
        if (i != 1 && arc[i] != h[i - 1] + 1) return (void)puts("-1");
    }
    printf("%s\n", ans.c_str());
}

bool _edmer;
int main() {
    cerr << (&_stmer - &_edmer) / 1024.0 / 1024.0 << "MB\n";
#ifndef cxqghzj
    /* freopen("string.in", "r", stdin); */
    /* freopen("string.out", "w", stdout); */
#endif
    int T = read();
    while (T--) solve();
    return 0;
}

标签:YC302A,string,省选,text,back,int,isl,push,include
From: https://www.cnblogs.com/cxqghzj/p/18252988

相关文章

  • 关于UEC++中FText、FString与FName
    FText用于本地化和用户界面显示文本。可以方便地将游戏文本翻译成不同的语言。FNameFName在UE中的功能与C#中的字符串池有相似之处,但它们的内部实现和用途有些不同。FName是一种轻量级的、不变的标识符类型,主要用于高效地处理字符串的比较和存储。特点:不可变:一旦创建,FNam......
  • String常用方法【随记】
    在Java中,String类提供了许多常用的方法来操作字符串。以下是一些最常用的方法:length()返回字符串的长度。Stringstr="Hello,World!";intlength=str.length();//13charAt(intindex)返回指定索引处的字符。charch=str.charAt(0);//'H'substring(intbeg......
  • 3. Longest Substring Without Repeating Characters
    Givenastrings,findthelengthofthelongestsubstringwithoutrepeatingcharacters.Example1:Input:s="abcabcbb"Output:3Explanation:Theansweris"abc",withthelengthof3.Example2:Input:s="bbbbb"Ou......
  • Document.SendStringToExecute方法
    出处:https://help.autodesk.com/view/OARX/2018/ENU/?guid=OREFNET-Autodesk_AutoCAD_ApplicationServices_Document_SendStringToExecute_string__MarshalAsUnmanagedType_U1__bool__MarshalAsUnmanagedType_U1__bool__MarshalAsUnmanagedType_U1__bool方法的API:publicvoidS......
  • C# 字符串(String)
    字符串在C#中是特殊的存在,它是引用类型(内存分配在托管堆上),属于不可改变的对象。任何对字符串的操作都会返回1个新的字符串。字符串加@符号,不会对转义字符进行处理,例如:stringstr1=@"C:\Windows\System32";字符串加$符号,可占位插入变量,例如:stringstr2=$"{str1}";.ToSt......
  • 深入理解Java中的StringBuffer与StringBuilder:性能、用法与代码样例
    在Java编程中,当我们需要频繁地修改字符串时,使用String类可能会遇到性能问题,因为String是不可变的(immutable)。为了解决这个问题,Java提供了两个可变字符串类:StringBuffer和StringBuilder。这两个类都允许我们在不创建新对象的情况下修改字符串,但它们之间也有一些重要的区别。......
  • fasterxml ToStringSerializerBase报错
    ToStringSerializerBase报错报错内容整合dubbo时报错Causedby:java.lang.NoClassDefFoundError:com/fasterxml/jackson/databind/ser/std/ToStringSerializerBase atcom.fasterxml.jackson.datatype.jsr310.JavaTimeModule.<init>(JavaTimeModule.java:158)~[jackson-dataty......
  • 高性能版本的零内存分配LikeString函数(ZeroMemAllocLikeOperator)
    继上一篇文章在.NETCore,除了VB的LikeString,还有其它方法吗?(四种LikeString实现分享)分享了四种实现方式,笔者对这四种实现方式,不管是执行性能还是内存分配性能上,都不太满意。那么是否有好的实现方法呢?答案是有的。今天我们就搬出ReadOnlySpan<T>这个非常好用的结构类型,它是在.N......
  • Java String 类详解
    在Java中,String类是一个非常重要的类,用于创建和操作字符串。字符串是字符的序列,它们被广泛应用于各种编程任务中,如文本处理、用户输入/输出、网络编程等。下面将详细介绍String类的一些基本特性和常用方法。1.字符串的创建在Java中,可以使用多种方式创建字符串对象。使用......
  • C++入门 string常用接口(下)
    目录string类的常用接口说明string类对象的修改操作(修饰符)operator+= &append&push_backassign&inserterase&replaceswap&pop_backstring类对象的非成员函数 operator+relationaloperators(关系运算符)getlineto_string&stoi取域名使用实践string类......