您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在洛谷问题页面的特定位置添加一个跳转到 VJudge 的链接
// ==UserScript== // @name 洛谷到 VJudge 跳转脚本 // @namespace http://tampermonkey.net/ // @version 3.1 // @description 在洛谷问题页面的特定位置添加一个跳转到 VJudge 的链接 // @author Kimi // @match https://www.luogu.com.cn/problem/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; function getProblemCode() { const path = window.location.pathname; const match = path.match(/^\/problem\/([^/]+)/); return match ? match[1] : null; } function getVJudgeURL(problemCode) { let match; if ((match = problemCode.match(/^(CF)(\d+)([A-Za-z]*)(\d*)$/))) { // 处理 CF + 数字 + 字母 + 可选数字 return `https://vjudge.net/problem/${encodeURIComponent(`CodeForces-${match[2]}${match[3]}${match[4]}`)}#author=GPT_zh`; } if ((match = problemCode.match(/^(P|B)(\d+)$/))) { const prefix = '洛谷'; return `https://vjudge.net/problem/${encodeURIComponent(`${prefix}-${problemCode}`)}#author=GPT_zh`; } if ((match = problemCode.match(/^(UVA)(\d+)$/))) { return `https://vjudge.net/problem/${encodeURIComponent(`UVA-${match[2]}`)}#author=GPT_zh`; } if ((match = problemCode.match(/^(SP)(\d+)$/))) { const span = document.querySelector('span[title*=" - "]'); if (span) { const title = span.getAttribute('title'); const contestName = title.split(' - ')[0]; return `https://vjudge.net/problem/${encodeURIComponent(`SPOJ-${contestName}`)}#author=GPT_zh`; } return null; } if ((match = problemCode.match(/^AT_(.+)$/))) { return `https://vjudge.net/problem/${encodeURIComponent(`AtCoder-${match[1]}`)}#author=GPT_zh`; } if ((match = problemCode.match(/^AT(.+)$/))) { return `https://vjudge.net/problem/${encodeURIComponent(`AtCoder-${match[1]}`)}#author=GPT_zh`; } return null; } function injectVJudgeLink(vjudgeURL) { const actionDiv = document.querySelector('div.action'); if (actionDiv) { if (!actionDiv.querySelector('a.vjudge-link')) { const link = document.createElement('a'); link.href = vjudgeURL; link.target = '_blank'; link.style.marginLeft = '10px'; link.textContent = '跳转至 VJudge'; link.classList.add('vjudge-link'); actionDiv.appendChild(link); console.log('VJudge链接已成功注入:', vjudgeURL); } } else { console.warn('Luogu to VJudge Script: 未找到目标元素 "div.action"。'); } } function main() { const problemCode = getProblemCode(); if (!problemCode) { console.warn('Luogu to VJudge Script: 无法提取问题代码。'); return; } const vjudgeURL = getVJudgeURL(problemCode); if (!vjudgeURL) { console.warn(`Luogu to VJudge Script: 未找到问题代码 "${problemCode}" 对应的 VJudge 映射。`); return; } injectVJudgeLink(vjudgeURL); } function observeDOM() { const observer = new MutationObserver((mutations, obs) => { const actionDiv = document.querySelector('div.action'); if (actionDiv) { main(); obs.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true }); } function init() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { main(); observeDOM(); }); } else { main(); observeDOM(); } } init(); })();