一个人能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己。 — KMP
题目描述
给定一个字符串text
,以及一个子串sub
,所有字符串中只包含大小写英文字母以及阿拉伯数字。
子串sub
在字符串text
中多次作为子串出现。
求出子串sub
在字符串text
中所有出现的位置的起始下标。
输入格式
第一行输入整数n
,表示字符串sub
的长度。
第二行输入字符串sub
。
第三行输入整数m
,表示字符串text
的长度。
第四行输入字符串text
。
输出格式
共一行,输出所有出现位置的起始下标(下标从0
开始计数),整数之间用空格隔开。
数据范围
1≤n≤105,1≤m≤106
可以先看灯神的讲解后,再来看代码。
#include<iostream> using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
int nex[N], n, m; char text[M], sub[N];
void kmp() { for (int i = 2, j = 0; i <= n; i++) { while (j && sub[i] != sub[j + 1]) j = nex[j]; if (sub[i] == sub[j + 1]) j++; nex[i] = j; }
for (int i = 1, j = 0; i <= m; i++) { while (j && text[i] != sub[j + 1]) j = nex[j]; if (text[i] == sub[j + 1]) j++; if (j == n) { cout << i - n << ' '; j = nex[j]; } } }
int main() { cin >> n >> sub + 1 >> m >> text + 1; kmp(); return 0; }
|