【洛谷】P3375 【模板】KMP字符串匹配

题目地址:

https://www.luogu.com.cn/problem/P3375

题目描述:
给出两个字符串 s 1 s_1 s1 s 2 s_2 s2,若 s 1 s_1 s1的区间 [ l , r ] [l, r] [l,r]子串与 s 2 s_2 s2完全相同,则称 s 2 s_2 s2 s 1 s_1 s1中出现了,其出现位置为 l l l。现在请你求出 s 2 s_2 s2 s 1 s_1 s1中所有出现的位置。定义一个字符串 s s s的border为 s s s的一个非 s s s本身的子串 t t t,满足 t t t既是 s s s的前缀,又是 s s s的后缀。对于 s 2 s_2 s2,你还需要求出对于其每个前缀 s ′ s' s的最长border的长度。

输入格式:
第一行为一个字符串,即为 s 1 s_1 s1。第二行为一个字符串,即为 s 2 s_2 s2

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

数据范围:
本题采用多测试点捆绑测试,共有 3 3 3个子任务。
Subtask1(30 points): ∣ s 1 ∣ ≤ 15 ∣s_1∣≤15 s115 ∣ s 2 ∣ ≤ 5 ∣s_2∣≤5 s25
Subtask2(40 points): ∣ s 1 ∣ ≤ 1 0 4 ∣s_1∣≤10_4 s1104 ∣ s 2 ∣ ≤ 1 0 2 ∣s_2∣≤10^2 s2102
Subtask3(30 points):无特殊约定。
对于全部的测试点,保证 1 ≤ ∣ s 1 ∣ , ∣ s 2 ∣ ≤ 1 0 6 1 \leq |s_1|,|s_2| \leq 10^6 1s1,s2106 1 ≤ ∣ s 1 ∣ , ∣ s 2 ∣ ≤ 1 0 6 1≤∣s_1∣,∣s_2∣≤10^6 1s1,s2106 s 1 , s 2 s_1, s_2 s1,s2中均只含大写英文字母。

参考https://blog.csdn.net/qq_46105170/article/details/113805346。由于这里需要求border长度,所以要用非优化版的KMP,并且next数组要多开一位。同时这里下标从 1 1 1开始,所以要将匹配的下标加 1 1 1后输出。代码如下:

#include <iostream>
#include <vector>
using namespace std;

vector<int> buildNe(string p) {
    
    
    int m = p.size();
    vector<int> ne = vector<int>(m + 1, 0);
    for (int i = 0, j = ne[0] = -1; i < m; )
        if (j == -1 || p[i] == p[j]) ne[++i] = ++j;
        else j = ne[j];

    return ne;
}

int main() {
    
    
    string s, p;
    cin >> s >> p;

    auto ne = buildNe(p);
    for (int i = 0, j = 0; i < s.size(); ) {
    
    
        if (j == -1 || s[i] == p[j]) i++, j++;
        else j = ne[j];

        if (j == p.size()) {
    
    
        	// 下标加1输出
            printf("%d\n", i - j + 1);
            // 假装最后一位没有匹配
            i--;
            j = ne[--j];
        }
    }

    for (int i = 1; i <= p.size(); i++) printf("%d ", ne[i]);

    return 0;
}

时间复杂度 O ( l s 1 + l s 2 ) O(l_{s_1}+l_{s_2}) O(ls1+ls2),空间 O ( l s 2 ) O(l_{s_2}) O(ls2)

Guess you like

Origin blog.csdn.net/qq_46105170/article/details/120756030