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

《P3375 【模板】KMP》

题目描述

给出两个字符串 s1​ 和 s2​,若 s1​ 的区间 [l,r] 子串与 s2​ 完全相同,则称 s2​ 在 s1​ 中出现了,其出现位置为 l。
现在请你求出 s2​ 在 s1​ 中所有出现的位置。

定义一个字符串 s 的 border 为 s 的一个非 s 本身的子串 t,满足 t 既是 s 的前缀,又是 s 的后缀。
对于 s2​,你还需要求出对于其每个前缀 s′ 的最长 border t′ 的长度。

输入格式

第一行为一个字符串,即为 s1​。
第二行为一个字符串,即为 s2​。

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 s2​ 在 s1​ 中出现的位置。
最后一行输出 ∣s2​∣ 个整数,第 i 个整数表示 s2​ 的长度为 i 的前缀的最长 border 长度。

输入输出样例

输入 #1复制

ABABABC
ABA

输出 #1复制

1
3
0 0 1 

说明/提示

样例 1 解释

对于 s2​ 长度为 3 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 1。

数据规模与约定

本题采用多测试点捆绑测试,共有 3 个子任务

  • Subtask 1(30 points):∣s1​∣≤15,∣s2​∣≤5。
  • Subtask 2(40 points):∣s1​∣≤104,∣s2​∣≤102。
  • Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 1≤∣s1​∣,∣s2​∣≤106,s1​,s2​ 中均只含大写英文字母。

代码实现:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// 计算前缀函数(next数组)
vector<int> compute_prefix_function(const string& pattern) {
    int m = pattern.length();
    vector<int> next(m, 0);
    int len = 0;
    int i = 1;
    
    while (i < m) {
        if (pattern[i] == pattern[len]) {
            len++;
            next[i] = len;
            i++;
        } else {
            if (len != 0) {
                len = next[len - 1];
            } else {
                next[i] = 0;
                i++;
            }
        }
    }
    return next;
}

// KMP字符串匹配算法
vector<int> kmp_search(const string& text, const string& pattern, const vector<int>& next) {
    vector<int> positions;
    int n = text.length();
    int m = pattern.length();
    int i = 0;  // 文本的索引
    int j = 0;  // 模式的索引
    
    while (i < n) {
        if (pattern[j] == text[i]) {
            j++;
            i++;
        }
        
        if (j == m) {
            positions.push_back(i - j + 1);  // 存储出现位置(1-based)
            j = next[j - 1];
        } else if (i < n && pattern[j] != text[i]) {
            if (j != 0) {
                j = next[j - 1];
            } else {
                i++;
            }
        }
    }
    return positions;
}

int main() {
    string s1, s2;
    cin >> s1 >> s2;
    
    // 计算前缀函数
    vector<int> next = compute_prefix_function(s2);
    
    // 执行KMP搜索
    vector<int> positions = kmp_search(s1, s2, next);
    
    // 输出出现位置(使用传统迭代器方式)
    for (vector<int>::iterator it = positions.begin(); it != positions.end(); ++it) {
        cout << *it << endl;
    }
    
    // 输出前缀函数结果
    for (int i = 0; i < s2.length(); i++) {
        cout << next[i] << (i == s2.length() - 1 ? "\n" : " ");
    }
    
    return 0;
}

相关文章:

  • 深度学习笔记24-LSTM火灾预测(Ptorch)
  • Python排序函数全面指南:从基础到高级
  • 电子电路:什么是电磁耦合?
  • PotPlayer 4K 本地万能影音播放器
  • [特殊字符] 在线音频剪辑网站上线啦!
  • CSS3动画
  • java使用aspose合并exl单元格
  • 掌握递归:编程中的优雅艺术
  • 智能建筑时代来临,楼宇自控技术成智能建筑标配新趋势
  • R语言开始绘图--柱状图
  • Linux——网络基础概念
  • 吃出 “颈” 松:痉挛性斜颈的饮食调养之道
  • ATSHA204A 加密芯片技术解析与破解方法
  • 嵌入式学习笔记 - freeRTOS链表中pxIndex->pxPrevious 与pxIndex->pxPrevious->的区别
  • 遥感解译项目Land-Cover-Semantic-Segmentation-PyTorch之一推理模型
  • 【生成模型】【基础知识】CFG与CFG蒸馏
  • 【Java高阶面经:消息队列篇】25、Kafka消息积压应对:从应急处理到架构根治
  • 深入解析自然语言处理中的语言转换方法
  • 《全志T3》_嵌入式产品Ubuntu操作系统启动详解一
  • 云存储迁移遇瓶颈?大文件跨平台传输加速指南
  • 佛山电商网站制作/网站首页的优化
  • 网站建立的关键技术/seo服务是什么意思
  • 网站算信息化建设/企业网站搜索优化网络推广
  • 世界四大广告公司/企业站seo价格
  • 设计网站需要哪些流程/网络工具
  • 如何做中英切换的网站/咖啡seo是什么意思