{ }codelper
分割字符串字典查找P0236

读取地址后面的设置

给出一行网址问号后面的设置字符串。
设置字符串只由小写英文字母、数字、'=' 和 '&' 组成。
先把设置字符串按 '&' 分开。
分出的片段中,空片段要丢掉。
& 连在一起,或开头、结尾有 & 时,会产生空片段。
对每个剩下的片段,第一个 '=' 前面是名字,后面是值。
值里可能还有 '=',值也可能是空字符串。
没有 '=' 的片段整个是名字,值是空字符串。
没有片段以 '=' 开头。
第二行给出问题数 q,接下来 q 行每行给出一个名字。
第一行输出剩下的片段个数。
接着对每个问题输出一行:把拥有这个名字的片段的值按出现顺序逐个用方括号括起来,不加空格地连起来。
值是空字符串时输出 []。
没有片段拥有这个名字时输出 -。

输入
设置字符串有 1~10,000 个字符,1 ≤ q ≤ 100,问到的名字由小写字母和数字组成,1~10 个字符
输出
第一行是片段个数,接下来 q 行是每个问题的值或 -
样例 1 · stdin
page=2&sort=new&&tag=a&tag=b=c&debug&
4
tag
debug
page
size
stdout
5
[a][b=c]
[]
[2]
-
样例 2 · stdin
&&&
1
a
stdout
0
-
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

8 种语言都有分割函数,但对空片段和“分几次”的处理各不相同。
Python split("&")、JS/TS split("&") 和 Craykon 分割("&") 会保留空片段,"&&&" 会变成 4 个空字符串,要自己过滤。
Java split("&") 按正则表达式分割,只丢掉末尾的空片段,开头和中间的空片段会保留。
C# Split('&', StringSplitOptions.RemoveEmptyEntries) 会丢掉所有空片段。
C strtok 把连续的 & 当作一个并跳过空片段,正好适合 '&'。
但如果 '=' 也用 strtok 切,"k==" 的值 "=" 就没了,所以要用 strchr 只找第一个 '='。
C++ 的 std::string 没有分割函数,常用 getline(stream, piece, '&') 逐个取出片段,再用 find('=') 切开。
这道题的陷阱是 '=' 只能分一次。
Python partition("=") 或 split("=", 1)、Java split("=", 2)、C# Split('=', 2) 只在第一个 '=' 处切开,剩下的留在值里。
JS/TS 的 split("=", 2) 名字相同,意思却不同。
它只保留前两段、丢掉其余部分,"b=c=d" 会变成 ["b", "c"],所以要用 indexOf("=") 和 slice 切。
Craykon 也用 查找位置("=") 和 截取 切。
像 Java split("=") 这样不加上限地切,"k==" 会变成 ["k"],值整个丢失。
同一个名字出现两次时要显示所有值,所以字典里放的是值的列表,而不是一个值。

Pythonmain.py · 18 行
line = input()q = int(input())values = {}  # 이름 → 값 목록(나온 차례대로)count = 0for piece in line.split("&"):    if piece == "":        continue  # &&·맨 앞·맨 뒤의 &가 만든 빈 조각은 버린다    count += 1    # 처음 나오는 '='에서만 한 번 나눈다(값 안의 '='는 그대로)    name, _, value = piece.partition("=")    values.setdefault(name, []).append(value)print(count)for _ in range(q):    name = input().strip()    if name in values:        print("".join(f"[{v}]" for v in values[name]))    else:        print("-")
JavaScriptmain.js · 20 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[1]);const values = new Map(); // 이름 → 값 배열(나온 차례대로)let count = 0;for (const piece of lines[0].trim().split("&")) {  if (piece === "") continue; // 빈 조각은 버린다  count++;  // 처음 나오는 '='에서만 자른다. split("=")은 값 안의 '='까지 자른다  const at = piece.indexOf("=");  const name = at < 0 ? piece : piece.slice(0, at);  const value = at < 0 ? "" : piece.slice(at + 1);  if (!values.has(name)) values.set(name, []);  values.get(name).push(value);}const out = [String(count)];for (let i = 0; i < q; i++) {  const vs = values.get(lines[2 + i].trim());  out.push(vs ? vs.map((v) => `[${v}]`).join("") : "-");}console.log(out.join("\n"));
TypeScriptmain.ts · 22 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[1]);const values = new Map<string, string[]>(); // 이름 → 값 배열(나온 차례대로)let count = 0;for (const piece of lines[0].trim().split("&")) {  if (piece === "") continue; // 빈 조각은 버린다  count++;  // 처음 나오는 '='에서만 자른다. split("=")은 값 안의 '='까지 자른다  const at: number = piece.indexOf("=");  const name: string = at < 0 ? piece : piece.slice(0, at);  const value: string = at < 0 ? "" : piece.slice(at + 1);  const list: string[] = values.get(name) ?? [];  list.push(value);  values.set(name, list);}const out: string[] = [String(count)];for (let i = 0; i < q; i++) {  const vs: string[] | undefined = values.get(lines[2 + i].trim());  out.push(vs ? vs.map((v) => `[${v}]`).join("") : "-");}console.log(out.join("\n"));
JavaMain.java · 37 行
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        String line = in.readLine().trim();        int q = Integer.parseInt(in.readLine().trim());        Map<String, List<String>> values = new HashMap<>(); // 이름 → 값 목록(나온 차례대로)        int count = 0;        // Java의 split은 맨 뒤의 빈 조각을 버리지만 맨 앞·가운데의 빈 조각은 남긴다        for (String piece : line.split("&")) {            if (piece.isEmpty()) continue;            count++;            // 한도 2: 처음 '='에서 한 번만 자르고, 뒤의 빈 문자열도 남긴다            String[] kv = piece.split("=", 2);            String value = kv.length > 1 ? kv[1] : "";            values.computeIfAbsent(kv[0], k -> new ArrayList<>()).add(value);        }        StringBuilder out = new StringBuilder();        out.append(count).append('\n');        for (int i = 0; i < q; i++) {            List<String> vs = values.get(in.readLine().trim());            if (vs == null) {                out.append("-\n");                continue;            }            for (String v : vs) out.append('[').append(v).append(']');            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 43 行
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        string line = Console.ReadLine().Trim();        int q = int.Parse(Console.ReadLine());        var values = new Dictionary<string, List<string>>(); // 이름 → 값 목록(나온 차례대로)        int count = 0;        // RemoveEmptyEntries가 빈 조각을 버린다        foreach (string piece in line.Split('&', StringSplitOptions.RemoveEmptyEntries))        {            count++;            // 한도 2: 처음 '='에서 한 번만 자른다            string[] kv = piece.Split('=', 2);            string value = kv.Length > 1 ? kv[1] : "";            if (!values.TryGetValue(kv[0], out var list))            {                list = new List<string>();                values[kv[0]] = list;            }            list.Add(value);        }        var sb = new StringBuilder();        sb.Append(count).Append('\n');        for (int i = 0; i < q; i++)        {            if (values.TryGetValue(Console.ReadLine().Trim(), out var vs))            {                foreach (string v in vs) sb.Append('[').Append(v).Append(']');                sb.Append('\n');            }            else            {                sb.Append("-\n");            }        }        Console.Write(sb);    }}
C++main.cpp · 36 行
#include <iostream>#include <map>#include <sstream>#include <string>#include <vector> int main() {    std::string line, piece;    std::getline(std::cin, line);    if (!line.empty() && line.back() == '\r') line.pop_back();    std::map<std::string, std::vector<std::string>> values; // 이름 → 값 목록(나온 차례대로)    int count = 0;    std::stringstream ss(line);    // getline에 구분 글자를 주면 빈 조각도 하나씩 돌려준다    while (std::getline(ss, piece, '&')) {        if (piece.empty()) continue;        count++;        std::size_t at = piece.find('='); // 처음 '='만        if (at == std::string::npos) values[piece].push_back("");        else values[piece.substr(0, at)].push_back(piece.substr(at + 1));    }    std::cout << count << '\n';    int q;    std::cin >> q;    std::string key;    for (int i = 0; i < q; i++) {        std::cin >> key;        auto it = values.find(key);        if (it == values.end()) {            std::cout << "-\n";            continue;        }        for (const auto &v : it->second) std::cout << '[' << v << ']';        std::cout << '\n';    }}
Cmain.c · 39 行
#include <stdio.h>#include <string.h> static char line[10005];static char *names[5001], *vals[5001]; int main(void) {    int q, count = 0;    if (!fgets(line, sizeof line, stdin)) return 0;    line[strcspn(line, "\r\n")] = '\0';    /* strtok은 이어진 &를 하나로 보고 빈 조각을 건너뛴다 — 이 문제에는 딱 맞다 */    for (char *piece = strtok(line, "&"); piece; piece = strtok(NULL, "&")) {        /* '='는 strtok으로 자르면 "a==b"의 '='가 사라진다. 처음 '='만 strchr로 찾는다 */        char *eq = strchr(piece, '=');        if (eq) {            *eq = '\0';            vals[count] = eq + 1;        } else {            vals[count] = "";        }        names[count] = piece;        count++;    }    printf("%d\n", count);    scanf("%d", &q);    char key[16];    for (int i = 0; i < q; i++) {        scanf("%15s", key);        int found = 0;        for (int j = 0; j < count; j++) {            if (strcmp(names[j], key) == 0) {                printf("[%s]", vals[j]);                found = 1;            }        }        puts(found ? "" : "-");    }    return 0;}
Craykonmain.cray · 44 行
line = 控制台.读行().去空白();q = 控制台.读行().转数字();values = 字典(); // 이름 → 값 목록(나온 차례대로)count = 0;遍历 (piece 在 line.分割("&")){    如果 (piece == "")    {        继续; // 빈 조각은 버린다    }    count += 1;    // 처음 나오는 '='에서만 자른다    at = piece.查找位置("=");    name = piece;    value = "";    如果 (at >= 0)    {        name = piece.截取(0, at);        value = piece.截取(at + 1);    }    如果 (!values.包含(name))    {        values[name] = [];    }    values[name].添加(value);}控制台.输出(count);循环 (i = 0; i < q; i++){    key = 控制台.读行().去空白();    如果 (values.包含(key))    {        out = "";        遍历 (v 在 values[key])        {            out += "[" + v + "]";        }        控制台.输出(out);    }    否则    {        控制台.输出("-");    }}