1 条题解

  • 0
    @ 2025-6-10 21:04:25

    题意分析

    题目要求从多块损坏的机械手表中推断火山爆发的最可能时间区间。每块手表有三根外观相同的指针(时、分、秒),且表盘可任意旋转,导致时间解读不唯一。需考虑所有可能的指针排列和旋转角度,找到包含所有手表候选时间的最短区间。时间以12小时制表示,秒针每秒移动一格,分针每60秒移动一格,时针每12分钟移动一格。

    解题思路

    代码使用KMP算法处理时间匹配:1)预处理目标时间序列的next数组;2)对每个手表,枚举所有可能的指针排列和旋转角度,生成候选时间序列;3)动态维护当前时间序列的最长匹配前缀长度,当匹配到目标序列时回溯删除;4)最终输出剩余序列表示的最短时间区间。需注意:1)处理时间时需模12小时;2)输出格式要求严格;3)最短区间优先选择较早的开始时间。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000005
    int nex[N], f[N];
    char an[N];
    void get_nex(char b[], int len)
    {
        nex[1] = nex[0] = 0;
        for (int i = 2, j = 0; i < len; i++) {
            while (j > 0 && b[i] != b[j + 1]) j = nex[j];
            if (b[i] == b[j + 1]) j++;
            nex[i] = j;
        }
    }
    void solve(char a[], int lena, char b[], int lenb)
    {
        int ans = 0;
        //约定下标从1开始 
        for (int i = 1, j = 0; i <= lena; i++) {
            j = f[ans];
            an[++ans] = a[i];
            while (j > 0 && (j == lenb || an[ans] != b[j + 1])) j = nex[j];
            if (an[ans] == b[j + 1]) j++;
            f[ans] = j;
            if (j == lenb) ans -= lenb;
        }
        for (int i = 1; i <= ans; i++)
            printf("%c", an[i]);
    }
    char a[N], b[N];
    int main()
    {
        scanf("%s%s", a + 1, b + 1);
        int len = strlen(b + 1);
        get_nex(b, len);
        int len1 = strlen(a + 1);
        solve(a, len1, b, len);
    }
    
    • 1

    信息

    ID
    2933
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者