当前位置: 首页 > news >正文

题解:AtCoder AT_awc0062_d Nearly Identical Signal Patterns

【题目来源】

AtCoder:D - Nearly Identical Signal Patterns

【题目描述】

Takahashi is analyzing the log of a communication system. In this system, a bit string \(S\) of length \(N\) consisting only of 0 and 1 is recorded.
高桥正在分析一个通信系统的日志。在这个系统中,记录了一个长度为 \(N\) 的、仅由 01 组成的比特字符串 \(S\)

Takahashi wants to find pairs of "nearly identical" intervals in this signal log.
高桥想在这个信号日志中找到"近乎相同"的区间对。

A contiguous substring of \(S\) is represented by a pair of starting position \(l\) and ending position \(r\), denoted \((l, r)\) (\(1 \leq l \leq r \leq N\)). This refers to the contiguous portion from the \(l\)-th character to the \(r\)-th character of \(S\), and its length is \(r - l + 1\).
\(S\) 的一个连续子串由其起始位置 \(l\) 和结束位置 \(r\) 表示,记为 \((l, r)\)\(1 \leq l \leq r \leq N\))。这指的是 \(S\) 中从第 \(l\) 个字符到第 \(r\) 个字符的连续部分,其长度为 \(r - l + 1\)

A pair of two contiguous substrings \(((l_1, r_1), (l_2, r_2))\) is called a "nearly identical" pair if and only if all of the following conditions are satisfied:
两个连续子串 \(((l_1, r_1), (l_2, r_2))\) 被称为"近乎相同"对,当且仅当满足以下所有条件:

  • \((l_1, r_1) \neq (l_2, r_2)\). That is, \(l_1 \neq l_2\) or \(r_1 \neq r_2\).
    \((l_1, r_1) \neq (l_2, r_2)\)。也就是说,\(l_1 \neq l_2\)\(r_1 \neq r_2\)
  • \(r_1 - l_1 = r_2 - l_2\). That is, the two contiguous substrings have equal length.
    \(r_1 - l_1 = r_2 - l_2\)。也就是说,两个连续子串的长度相等。
  • Let \(L\) be the length of the two contiguous substrings. When comparing the \(i\)-th characters from the beginning (\(1 \leq i \leq L\)), there is exactly \(1\) position \(i\) where the characters differ (that is, the Hamming distance is exactly \(1\)).
    \(L\) 为两个连续子串的长度。当比较它们的第 \(i\) 个字符(\(1 \leq i \leq L\))时,恰好有 \(1\) 个位置 \(i\) 的字符不同(即汉明距离恰好为 \(1\))。

Pairs are counted as unordered. That is, \(((l_1, r_1), (l_2, r_2))\) and \(((l_2, r_2), (l_1, r_1))\) are considered the same pair.
无序计数对。也就是说,\(((l_1, r_1), (l_2, r_2))\)\(((l_2, r_2), (l_1, r_1))\) 被视为同一个对。

Note that substrings are distinguished by their position pair \((l, r)\). Even if the actual string contents are identical, if \((l_1, r_1) \neq (l_2, r_2)\), they are treated as different substrings.
注意,子串通过其位置对 \((l, r)\) 来区分。即使实际的字符串内容相同,如果 \((l_1, r_1) \neq (l_2, r_2)\),它们也被视为不同的子串。

Find the number of pairs that satisfy the conditions.
求满足条件的对的数量。

【输入】

\(N\)
\(S\)

  • The first line contains an integer \(N\) representing the length of the bit string.
  • The second line contains a string \(S\) of length \(N\) consisting only of 0 and 1.

【输出】

Output the number of unordered pairs satisfying the conditions as a single integer on one line.

【输入样例】

3
101

【输出样例】

2

【核心思想】

  1. 问题分析:给定长度为 \(N\) 的二进制字符串 \(S\),求所有无序子串对 \(((l_1, r_1), (l_2, r_2))\) 的数量,要求两子串长度相等且汉明距离恰好为 \(1\)(即恰好有一个位置字符不同)。子串通过位置 \((l, r)\) 区分,即使内容相同,位置不同也视为不同子串。这是一个字符串哈希问题,关键在于快速判断子串相等并高效统计满足条件的对数。

  2. 算法选择

    • 字符串哈希(Rolling Hash):预处理前缀哈希数组,将任意子串的相等判断转化为 \(O(1)\) 的哈希值比较
    • 二分求 LCP:利用哈希的 \(O(1)\) 比较,二分查找两个后缀的最长公共前缀长度
    • 巧妙计数:对于固定的起始位置对 \((i, j)\),通过两次 LCP 将"恰好一个不同字符"的约束分解,将方案数转化为第二次 LCP 的长度加 \(1\)
  3. 关键步骤

    • 预处理
      • 计算前缀哈希数组 \(h\) 和幂次数组 \(p\)(基数通常取 \(131\)\(13331\)
      • \(h[i] = h[i-1] \times P + s[i]\)\(p[i] = p[i-1] \times P\)
    • 枚举起始位置对:遍历 \(1 \leq i < j \leq N\)
    • 第一次 LCP:计算 \(p_1 = \text{LCP}(i, j)\),即从位置 \(i\)\(j\) 开始的最长公共前缀长度
    • 跳过不同字符\(ni = i + p_1 + 1\)\(nj = j + p_1 + 1\)(跳过第一个不同字符)
    • 边界判断:若 \(ni > N\)\(nj > N\),说明一个子串是另一个的前缀,贡献为 \(1\)(仅长度 \(p_1\) 的子串)或直接跳过
    • 第二次 LCP:计算 \(p_2 = \text{LCP}(ni, nj)\),即跳过不同字符后,后面部分的最长公共前缀长度
    • 累加贡献\(ans \mathrel{+}= p_2 + 1\)。含义:两子串前面 \(p_1\) 个字符相同,中间 \(1\) 个字符不同,后面可以延伸 \(0\)\(p_2\) 个相同字符,共 \(p_2 + 1\) 种长度选择
    • 输出答案 \(ans\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N^2 \log N)\)。枚举起始位置对 \(O(N^2)\),每次两次 LCP 二分查找 \(O(\log N)\)
    • 空间复杂度:\(O(N)\),前缀哈希数组和幂次数组
  5. 字符串哈希的核心思想

    • 滚动哈希:将字符串看作 \(P\) 进制数,前缀哈希使任意子串的哈希值可在 \(O(1)\) 内计算:\(\text{get}(l, r) = h[r] - h[l-1] \times p[r-l+1]\)
    • LCP 二分:利用哈希的 \(O(1)\) 比较能力,二分查找两个后缀首次不同的位置,从而得到最长公共前缀长度
    • 组合计数转化:将"恰好一个不同"的约束拆解为"相同前缀 + 一个不同 + 相同后缀",利用 LCP 快速计算相同前缀和相同后缀的长度,从而将方案数转化为后缀 LCP 长度加 \(1\)
    • 冲突处理:使用双哈希或 \(64\) 位自然溢出(unsigned long long)降低哈希冲突概率
    • 适用于子串相等判断、最长公共前缀、回文检测、字符串匹配等场景

【算法标签】

字符串哈希

【代码详解】

#include <bits/stdc++.h>
using namespace std;typedef unsigned long long ULL;  // 定义无符号长整型别名
#define int long long  // 将int定义为long long类型
const int P = 131, N = 5005;  // P:哈希基数(131), N:最大长度(5005)
int n;  // 字符串长度
int ans;  // 最终答案
string s;  // 输入字符串
ULL h[N];  // 哈希前缀数组
ULL p[N];  // 哈希基数幂次数组// 初始化哈希数组
void init()
{p[0] = 1;  // P^0 = 1h[0] = 0;  // 空串的哈希值为0for (int i = 1; i <= n; i++){p[i] = p[i - 1] * P;  // 计算P^ih[i] = h[i - 1] * P + s[i];  // 计算前缀哈希值}
}// 获取子串s[l..r]的哈希值
ULL get(int l, int r)
{return h[r] - h[l - 1] * p[r - l + 1];
}// 判断两个子串是否相等
bool substr(int l1, int r1, int l2, int r2)
{return get(l1, r1) == get(l2, r2);
}// 计算从位置a和b开始的最长公共前缀长度
int lcp(int a, int b)
{int l = 0, r = n - max(a, b) + 1;  // 二分查找范围while (l < r){int mid = (l + r + 1) >> 1;  // 向上取整if (get(a, a + mid - 1) == get(b, b + mid - 1))  // 如果前mid个字符相等{l = mid;  // 增加下界}else{r = mid - 1;  // 减少上界}}return l;  // 返回最长公共前缀长度
}signed main()  // 因为使用了#define int long long,所以用signed
{cin >> n >> s;  // 输入字符串长度和字符串s = " " + s;  // 在字符串前添加空格,使下标从1开始init();  // 初始化哈希数组// 遍历所有位置对(i,j),其中i<jfor (int i = 1; i <= n; i++){for (int j = i + 1; j <= n; j++){int p1 = lcp(i, j);  // 计算从i和j开始的最长公共前缀长度int ni = i + p1;  // 跳过公共前缀后的位置iint nj = j + p1;  // 跳过公共前缀后的位置jif (ni > n || nj > n) continue;  // 如果跳过公共前缀后超出范围,跳过ni++;  // 移到下一个字符nj++;  // 移到下一个字符if (ni > n || nj > n)  // 如果移动后超出范围{ans += 1;  // 特殊情况:贡献为1continue;}int p2 = lcp(ni, nj);  // 计算新位置的最长公共前缀长度ans += (p2 + 1);  // 贡献为p2+1}}cout << ans << endl;  // 输出最终答案return 0;  // 程序正常结束
}

【运行结果】

3
101
2
http://www.jsqmd.com/news/1054580/

相关文章:

  • Mate Engine:打造你的专属免费虚拟桌面伙伴
  • 2026 年 6 月欧米茄官方售后门店资质实地查验报告 覆盖全国 60 + 正规服务点 - 欧米茄中国服务中心
  • Selenium自动化测试:彻底解决Chrome与Chromedriver环境配置难题
  • 2026合肥本土靠谱GEO优化服务商实测:合肥智拓GEO实力深度解析 - 行业深度观察C
  • 基于NXP MC56F83xxx DSC的PMSM无感FOC驱动开发实战
  • zteOnu深度解析:中兴光猫工厂模式认证与Telnet权限获取技术实现
  • 抖音批量下载工具:5分钟掌握免费批量下载技巧
  • Gemini 3.1 Pro延迟根因与DMXAPI全链路优化实战
  • LLM结构化经验表示Gene:从测试控制到自我进化的工程实践
  • WorkshopDL:跨平台Steam创意工坊模组下载完整指南
  • 考研英语阅读题源报刊|考研英语题源阅读|考研英语新题型题库
  • Claude代码路由机制:轻量Shell脚本实现本地安全调用
  • 2026年6月卡地亚官方腕表维修服务网络完成升级,多地标准化售后服务中心营业地址对外开放 - 卡地亚中国服务中心
  • 基于OWASP MASTG的移动应用安全测试报告撰写终极指南
  • 题解:AtCoder AT_awc0045_d Cell Division
  • 图神经网络在粒子加速器状态监测中的应用与优化
  • 3个核心优势:开源虚拟桌面伴侣Mate Engine的终极解决方案
  • [智能体-491]:第二增长曲线:贯穿企业、技术、个体、文明、物种的通用演化规律
  • 微信聊天记录永久保存终极指南:免费开源工具WeChatExporter详解
  • 2026合肥公办民办卫校实力排名、学费升学完整汇总一览! - 我叫小周
  • DSP56800E嵌入式开发:内联汇编与Intrinsic函数性能优化实战
  • TranslucentTB完整解决方案:Windows任务栏透明化终极指南
  • DSP56800到DSP56800E代码迁移:兼容性解析与性能优化实战
  • 广州保时捷老改新捷奥名车:本地服务商评测与行业解析 - 百航
  • 2026深圳黄金回收怎么选?避坑干货 + 真实门店测评汇总 - 沉迷学习28
  • 3个核心技巧:掌握AMD Ryzen处理器的终极调试工具SMUDebugTool
  • 2026德州黄金回收价格参考:行情走势与六家正规门店实测 - 余生黄金回收
  • 抖音实力强的直播公会推荐 - 舒雯文化
  • 2026年度卡地亚官方售后网点权威核验报告,覆盖全国六十余家服务门店地址公示 - 卡地亚中国服务中心
  • 光学衍射神经网络实战:3大突破性技术实现全光计算革命