2023NOIP A层联测10-子序列

news/2024/6/17 10:18:12 标签: 算法, c++

给定一个长为 n n n 的仅有小写英文字母构成字符串 S = S 1 S 2 ⋯ S n S=S_1S_2\cdots S_n S=S1S2Sn。我们定义一个字符串是好的,当且仅当它可以用两个不同的字母 xy 表示成 xyxyxyx... 的形式。例如,字符串 ababtotz 是好的,但字符串 abcaa 不是好的。

现在有 q q q 组询问,每次给定 1 ≤ l ≤ r ≤ n 1 \le l \le r \le n 1lrn,你想要求出,对于串 S S S 的子串 S [ l ⋯ r ] S[l \cdots r] S[lr],它最长的一个好的子序列的长度是多少,以及它可以被哪两个不同字符 xy 来表示。如果有多个最长的串,则输出字典序最小的一个串的 xy


预处理出 p r e i , j , n x t i , j pre_{i,j},nxt_{i,j} prei,j,nxti,j 分别表示第 i i i 个字符前/后第一个字符 j j j 的出现位置。

对于每个字符 S i S_i Si,考虑在只保留它时序列被分成了若干段(?????i?i??i????i?? ),预处理出 s u m i , j sum_{i,j} sumi,j 表示以 j j j 字符为分隔点,将序列分成若干段, S i S_i Si 所在的段及其之后的段含有 S i S_i Si 的个数减一。不懂?放个图就懂了。

在这里插入图片描述 可以递推求出 s u m i , j sum_{i,j} sumi,j

s u m i , j = s u m n x t i , S i + [ n x t i , S i > n x t i , j ] sum_{i,j}=sum_{nxt_{i,S_i}}+[nxt_{i,S_i}>nxt_{i,j}] sumi,j=sumnxti,Si+[nxti,Si>nxti,j]

意思就是如果 j j j 夹在 S i S_i Si 中间,就可以从后面转移过来。

对于每一次询问,枚举答案的两个字符 c 1 , c 2 c_1,c_2 c1,c2,找出区间内第一次和最后一次 c 1 c_1 c1 出现的位置 L , R L,R L,R 2 ( s u m L , c 1 − s u m R , c 1 ) + 1 + [ p r e r + 1 , c 2 > R ] 2(sum_{L,c_1}-sum_{R,c_1})+1+[pre_{r+1,c_2}>R] 2(sumL,c1sumR,c1)+1+[prer+1,c2>R] 就是最长的好子序列长度。这样就求出了答案。

具体实现看代码

#include<bits/stdc++.h>
using namespace std;
const int N=1.5e6+2;
char a[N];
int m,pre[N][26],nxt[N][26],sum[N][26];
int main()
{
    freopen("seq.in","r",stdin);
    freopen("seq.out","w",stdout);
    scanf("%s",a+1);
    int n=strlen(a+1);
    for(int i=1;i<=n+1;i++){
        for(int j=0;j<26;j++){
            if(a[i-1]==j+97) pre[i][j]=i-1;
            else pre[i][j]=pre[i-1][j];
        }
    }
    for(int i=0;i<26;i++) nxt[n+1][i]=n+1;
    for(int i=n;i>=0;i--){
        for(int j=0;j<26;j++){
            if(a[i+1]==j+97) nxt[i][j]=i+1;
            else nxt[i][j]=nxt[i+1][j];
        }
        for(int j=0;j<26;j++){
            sum[i][j]=sum[nxt[i][a[i]-97]][j]+(nxt[i][a[i]-97]>nxt[i][j]);
        }
    }
    scanf("%d",&m);
    for(int i=1,l,r;i<=m;i++){
        scanf("%d%d",&l,&r);
        int maxn=-1;
        char c1=0,c2=0;
        for(int i=0;i<26;i++){
            for(int j=0;j<26;j++){
                if(i==j) continue;
                if(nxt[l-1][i]>r) continue;
                int L=nxt[l-1][i],R=pre[r+1][i];
                int ans=(sum[L][j]-sum[R][j])*2+1+(pre[r+1][j]>R);
                if(ans>maxn) maxn=ans,c1=i+97,c2=j+97;
            }
        }
        printf("%d %c%c\n",maxn,c1,c2);
    }
}

http://www.niftyadmin.cn/n/5084346.html

相关文章

天猫用户重复购买预测(速通一)

天猫用户重复购买预测&#xff08;一&#xff09; 赛题理解1、评估指标2、赛题分析 理论知识1.缺失值处理2.不均衡样本3.常见的数据分布 数据探索探查影响复购的各种因素1.对店铺分析2.对用户分析3.对用户性别的分析4.对用户年龄的分析 特征工程1、特征工程介绍特征归一化类别型…

单目标应用:墨西哥蝾螈优化算法(Mexican Axolotl Optimization,MAO)求解微电网优化--MATLAB代码

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、墨西哥蝾螈优化算法MAO 墨西哥蝾螈优化算法&#xff08;Mexican Axolotl Optimization&#xff0c;MAO&#xff09;由Yenny Villuendas-Rey 1等人于2021…

Linux进阶-加深进程印象

进程 进程状态转换 一般来说&#xff0c;一个进程的开始都是从其父进程调用fork()函数开始&#xff0c;所以在系统一上电运行时&#xff0c;init进程就开始工作&#xff0c;在系统运行过程中&#xff0c;会不断启动新的进程&#xff08;要么由init进程启动&#xff0c;要么由被…

Hydra参数

kali的hyda参数 参数&#xff1a; hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e ns][-o FILE] [-t TASKS] [-M FILE [-T TASKS]] [-w TIME] [-f] [-s PORT] [-S] [-vV] server service [OPT] -R 继续从上一次进度接着破解。 -S 采用SSL链接。 -s PORT 可通…

goland 旧版本使用1.19环境

C:\Go\src\runtime\internal\sys\zversion.go // Code generated by go tool dist; DO NOT EDIT.package sysconst StackGuardMultiplierDefault 1const TheVersion go1.19引入其他包的标识符 package mainimport ("fmt""gotest/test")func main() {f…

Arduino驱动BMI160 6轴惯性运动传感器(惯性测量传感器篇)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序

【ccf-csp题解】第7次csp认证-第二题-俄罗斯方块-简单碰撞检测算法

题目描述 思路讲解 本题的主要思路是实现一个draw函数&#xff0c;这个函数可以绘制每一个状态的画布。然后从第一个状态往后遍历&#xff0c;当绘制到某一个状态发生碰撞时&#xff0c;答案就是上一个状态的画布。 此处的状态x实际就是在原来的15*10画布上的第x行开始画我们…

PyTorch 深度学习之加载数据集Dataset and DataLoader(七)

1. Revision: Manual data feed 全部Batch&#xff1a;计算速度&#xff0c;性能有问题 1 个 &#xff1a;跨越鞍点 mini-Batch:均衡速度与性能 2. Terminology: Epoch, Batch-Size, Iteration DataLoader: batch_size2, sheffleTrue 3. How to define your Dataset 两种处…