Luogu-to-Vjudge:一键跳转 VJudge 脚本

· · 科技·工程

一键跳转 VJudge 脚本

新版同步于 GitHub 仓库,可以去 Star 一下。

保命声明:完全开源免费,拒绝商业化。仅供学术研究,严禁用于一切非正当行为。脚本使用了 AI 辅助制作,本文章仅作为分享,希望可以优化各位的做题体验。

2025-11-24 upt:更新了脚本源码,修复了一些跳转bug。重新提交审核,感谢管理员。

脚本简介

洛谷VJudge 是两大高频使用的平台:

二者结合能大幅提升刷题效率。

随着洛谷 RMJ 下线,刷其他 OJ 的题目不再方便,而 VJudge 仍可提交 CF、AT、SPOJ 等题目,自由度较高。于是就有了这个脚本(网上旧脚本因洛谷新版 UI 已失效)。

方便快捷

手动在两个平台间切换、查找对应编号耗时费力。
「洛谷一键跳转 VJudge」 脚本适配洛谷新版 UI,支持 CF / SPOJ / AtCoder / UVA 四大平台题目一键跳转,自动识别题目编号并拼接 VJudge 链接,让跨平台刷题一步到位。

美观大气

视觉效果与洛谷原生按钮无缝融合:

脚本生成的按钮在背景色、字体、高度、对齐方式等方面均与原生按钮一致,不破坏页面美观;点击后于新标签页打开 VJudge 题目,不影响当前刷题进度。

使用指南

步骤 1:安装脚本管理器

在浏览器扩展商店搜索并安装 TampermonkeyViolentmonkey

相信很多人都喜欢用脚本优化做题体验。比如我:

步骤 2:添加脚本

  1. 打开 GitHub 仓库 下载源文件,脚本管理器会自动接管安装;
  2. 若未自动安装,可在脚本管理器内「新建用户脚本」,粘贴以下内容后保存:
// ==UserScript==
// @name         洛谷rmj一键跳转VJudge
// @namespace    http://tampermonkey.net/
// @version      3.1
// @description  支持洛谷CF/SPOJ/AtCoder/UVA题目跳转VJudge,修复CF带数字后缀的编号匹配
// @author       Justskr
// @match        https://www.luogu.com.cn/problem/CF*
// @match        https://www.luogu.com.cn/problem/SP*
// @match        https://www.luogu.com.cn/problem/AT*
// @match        https://www.luogu.com.cn/problem/UVA*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function getVjudgeUrl() {
        const luoguUrl = window.location.href;
        const luoguPath = window.location.pathname;

        if (luoguPath.startsWith('/problem/AT_')) {
            const atMatch = luoguPath.match(/AT_(\w+)/);
            return atMatch ? `https://vjudge.net/problem/AtCoder-${atMatch[1]}` : null;
        }
        else if (luoguPath.startsWith('/problem/UVA')) {
            const uvaMatch = luoguPath.match(/UVA(\d+)/);
            return uvaMatch ? `https://vjudge.net/problem/UVA-${uvaMatch[1]}` : null;
        }
        else if (luoguPath.startsWith('/problem/CF')) {
            // 修复CF编号匹配
            const cfMatch = luoguPath.match(/CF(\d+[A-Za-z\d]*)/);
            return cfMatch ? `https://vjudge.net/problem/CodeForces-${cfMatch[1]}` : null;
        }
        else if (luoguPath.startsWith('/problem/SP')) {
            let spojId = null;
            const originalLink = document.querySelector('a[href*="spoj.com/problems/"]');
            if (originalLink) {
                spojId = originalLink.href.split('/problems/')[1].replace('/', '');
            }
            else {
                const pageText = document.body.innerText;
                const spojTextMatch = pageText.match(/SPOJ\s*[-\s:]([A-Za-z0-9_-]+)/i);
                spojId = spojTextMatch ? spojTextMatch[1].trim() : null;
            }
            return spojId ? `https://vjudge.net/problem/SPOJ-${spojId}` : null;
        }

        return null;
    }

    const copyBtn = Array.from(document.querySelectorAll('button')).find(
        btn => btn.innerText.trim() === '复制题目'
    );

    const vjudgeUrl = getVjudgeUrl();
    if (copyBtn && vjudgeUrl) {
        const jumpBtn = document.createElement('button');
        jumpBtn.innerText = '跳转VJudge';

        const copyStyles = window.getComputedStyle(copyBtn);
        [
            'backgroundColor', 'color', 'border', 'borderRadius',
            'padding', 'fontSize', 'fontFamily', 'cursor', 'height',
            'lineHeight', 'textAlign', 'whiteSpace', 'verticalAlign',
            'display', 'marginTop', 'marginBottom'
        ].forEach(styleProp => {
            jumpBtn.style[styleProp] = copyStyles[styleProp];
        });

        jumpBtn.style.marginLeft = '5px';
        jumpBtn.style.minWidth = copyStyles.minWidth || '80px';

        jumpBtn.addEventListener('click', () => {
            window.open(vjudgeUrl, '_blank');
        });

        copyBtn.parentNode.insertBefore(jumpBtn, copyBtn.nextSibling);
    }
    else if (!vjudgeUrl) {
        const platform = luoguPath.match(/\/problem\/(\w+)/)[1].slice(0, 2);
        console.warn(`洛谷${platform}题目跳转VJudge:未找到有效题目标识符,请检查页面格式`);
    }
})();

步骤 3:一键跳转,即刻体验

打开洛谷任意支持平台的题目页,「复制题目」按钮右侧将出现「跳转 VJudge」按钮,点击即可直接跳转,无需手动输入编号!

后续可能更新「提交时重定向到 VJudge 提交界面」功能(大概率咕咕咕)。

完结撒花!