小红书笔试真题 9.13 - 避重口令(C++/Py/Java /Js/Go)

避重口令

小红书 9月13号 笔试真题 第一题

题目描述

短视频审核后台要把已过审成片的标题按发布时间依次拼接,得到小写字符串 SSS。SSS 的每一个子序列(含 SSS 本身与空串)都被视为已经占用的口令,不能再给新专题使用。

求最短的、不是 SSS 子序列的小写口令长度。

子序列:从原串中删除任意个(可以为零个)字符后,剩余字符保持相对顺序所形成的串。

输入描述

一行,仅含小写字母的字符串 SSS(1≤∣S∣≤1051\le |S|\le 10^51≤∣S∣≤105)。

输出描述

一行一个正整数,即最短未占用口令的长度。

样例1

输入

复制代码
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba

输出

复制代码
3

说明

SSS 由两段倒序的 262626 个小写字母拼接而成。任意单个字母、任意长度为 222 的小写串都是 SSS 的子序列(前半段取第一个字符、后半段取第二个字符即可)。SSS 中字母 aaa 只出现两次,故 aaa 不是子序列,最短长度为 333。

题解和思路

思路

实现思路:动态规划

  1. 定义dp数组,其中dp[i]表示从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
  2. 对于当前位置i
    • 如果某个字符c在s[i...]根本不存在,那么单个字符c就已经不是子序列,所以dp[i] = 1
    • 否则,选择一个字符 c,第一次匹配到它的位置是 j,那么后面还需要找一个不是 S[j+1...] 子序列的字符串。因此dp[i] = min(d[i], 1 + dp[j] + 1)
  3. 时间复杂度为O(N)

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    string s;
    cin >> s;
    int n = s.size();
    
    // i之后最近c的位置
    vector<vector<int>> nxt(n + 1, vector<int>(26));
    for (int c = 0; c < 26; c++) {
        nxt[n][c] = n;
    }
    
    for (int i = n - 1; i >= 0; i--) {
        nxt[i] = nxt[i + 1];
        nxt[i][s[i] - 'a'] = i;
    }
    
    const int INF = 1e9;
    // 从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
    vector<int> dp(n + 1, INF);
     // 空串之后,不存在任何字符可以匹配
    dp[n] = 1;
    
    for (int i = n -1; i >= 0; i--) {
        for (int c = 0; c < 26; c++) {
            int j = nxt[i][c];
            if (j == n) {
                //字符 c 在后面不存在
                dp[i] = 1;
                
            } else {
                dp[i] = min(dp[i], 1 + dp[j + 1]);
            }
        }
    }
    cout << dp[0] << endl;
    return 0;
}

Java

java 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String s = sc.next();
        int n = s.length();

        // i之后最近c的位置
        int[][] nxt = new int[n + 1][26];

        for (int c = 0; c < 26; c++) {
            nxt[n][c] = n;
        }

        for (int i = n - 1; i >= 0; i--) {
            System.arraycopy(nxt[i + 1], 0, nxt[i], 0, 26);
            nxt[i][s.charAt(i) - 'a'] = i;
        }

        final int INF = 1000000000;

        // 从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
        int[] dp = new int[n + 1];
        Arrays.fill(dp, INF);

        // 空串之后,不存在任何字符可以匹配
        dp[n] = 1;

        for (int i = n - 1; i >= 0; i--) {
            for (int c = 0; c < 26; c++) {
                int j = nxt[i][c];

                if (j == n) {
                    // 字符 c 在后面不存在
                    dp[i] = 1;
                } else {
                    dp[i] = Math.min(dp[i], 1 + dp[j + 1]);
                }
            }
        }

        System.out.println(dp[0]);
    }
}

python

python 复制代码
import sys

s = sys.stdin.readline().strip()
n = len(s)

# i之后最近c的位置
nxt = [[n] * 26 for _ in range(n + 1)]

for i in range(n - 1, -1, -1):
    nxt[i] = nxt[i + 1].copy()
    nxt[i][ord(s[i]) - ord('a')] = i

INF = 10**9

# 从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
dp = [INF] * (n + 1)

# 空串之后,不存在任何字符可以匹配
dp[n] = 1

for i in range(n - 1, -1, -1):
    for c in range(26):
        j = nxt[i][c]

        if j == n:
            # 字符 c 在后面不存在
            dp[i] = 1
        else:
            dp[i] = min(dp[i], 1 + dp[j + 1])

print(dp[0])

Javascript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('line', (s) => {
    s = s.trim();
    const n = s.length;

    // i之后最近c的位置
    const nxt = Array.from({ length: n + 1 }, () => new Array(26).fill(n));

    for (let c = 0; c < 26; c++) {
        nxt[n][c] = n;
    }

    for (let i = n - 1; i >= 0; i--) {
        nxt[i] = [...nxt[i + 1]];
        nxt[i][s.charCodeAt(i) - 97] = i;
    }

    const INF = 1e9;

    // 从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
    const dp = new Array(n + 1).fill(INF);

    // 空串之后,不存在任何字符可以匹配
    dp[n] = 1;

    for (let i = n - 1; i >= 0; i--) {
        for (let c = 0; c < 26; c++) {
            const j = nxt[i][c];

            if (j === n) {
                // 字符 c 在后面不存在
                dp[i] = 1;
            } else {
                dp[i] = Math.min(dp[i], 1 + dp[j + 1]);
            }
        }
    }

    console.log(dp[0]);
    rl.close();
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var s string
	fmt.Fscan(in, &s)

	n := len(s)

	// i之后最近c的位置
	nxt := make([][]int, n+1)

	for i := 0; i <= n; i++ {
		nxt[i] = make([]int, 26)
		for c := 0; c < 26; c++ {
			nxt[i][c] = n
		}
	}

	for i := n - 1; i >= 0; i-- {
		copy(nxt[i], nxt[i+1])
		nxt[i][s[i]-'a'] = i
	}

	const INF = int(1e9)

	// 从 S[i...n-1] 开始,最短的、不是 S[i...n-1] 子序列的字符串长度
	dp := make([]int, n+1)
	for i := 0; i <= n; i++ {
		dp[i] = INF
	}

	// 空串之后,不存在任何字符可以匹配
	dp[n] = 1

	for i := n - 1; i >= 0; i-- {
		for c := 0; c < 26; c++ {
			j := nxt[i][c]

			if j == n {
				// 字符 c 在后面不存在
				dp[i] = 1
			} else {
				if dp[i] > 1+dp[j+1] {
					dp[i] = 1 + dp[j+1]
				}
			}
		}
	}

	fmt.Fprintln(out, dp[0])
}
相关推荐
无限码力2 天前
小红书笔试真题 9.10 - 最小化峰值干扰(C++/Py/Java /Js/Go)
小红书·小红书笔试真题·小红书笔试真题题解·小红书最新笔试真题
无限码力2 天前
小红书笔试真题 9.10 - 双通道评测格网(C++/Py/Java /Js/Go)
小红书笔试·小红书笔试真题·小红书笔试题解·小红书校招笔试题目
feasibility.9 天前
MediaCrawler媒体采集平台安装与使用
爬虫·抖音·小红书·微博·bili
程序猿炎义3 个月前
一人内容团队——用Amazon Quick Desktop实现小红书从选题到发布的全流程自动化
大数据·人工智能·microsoft·自动化·小红书
小脑斧1234 个月前
AI Skills 全链路自动化运营实践:抖音热点、小红书种草与文生图一体化方案
大数据·人工智能·小红书·skills·自动化运营
Afans_fire4 个月前
从数据角度优化全媒体广告投放
小红书·广告投放·抖音运营·抖音代运营·小红书聚光
Afans_fire4 个月前
全域流量时代:如何用“漏斗模型”打通百度、抖音与小红书的营销闭环?
百度·内容运营·小红书·小红书运营·广告投放·巨量引擎
yoona10205 个月前
使用 Auto-Redbook-Skills 自动生成并发布redbook图文笔记
笔记·小红书·skills·redbook
深蓝电商API5 个月前
小红书商品笔记抓取:笔记ID与商品关联关系解析
爬虫·小红书