Link
https://www.acmicpc.net/problem/7575
Detail
단순 KMP 문제다. 다만 벡터의 복사를 최적화 하기위해서 함수의 오버로드와 iterator를 적극적으로 사용하였다.
Code
#include <bits/stdc++.h>
#define MOD 10007
#define MAX 1'000'000
using namespace std;
typedef long long ll;
typedef vector<int> program;
typedef program::iterator pIter;
typedef program::reverse_iterator rpIter;
// O(n)
bool contains_virus(
pIter start,
pIter end,
pIter sub_start,
pIter sub_end,
const vector<int>& pi
) {
// use kmp
int j = 0;
for (int i = 0; i < end - start; i++) {
while (j > 0 && start[i] != sub_start[j]) {
j = pi[j - 1];
}
if (start[i] == sub_start[j]) {
if (j == sub_end - sub_start - 1) {
return true;
}
j++;
}
}
return false;
}
bool contains_virus (
rpIter start,
rpIter end,
pIter sub_start,
pIter sub_end,
const vector<int>& pi
) {
// use kmp. reversed
int j = 0;
for (int i = 0; i < end - start; i++) {
while (j > 0 && start[i] != sub_start[j]) {
j = pi[j - 1];
}
if (start[i] == sub_start[j]) {
if (j == sub_end - sub_start - 1) {
return true;
}
j++;
}
}
return false;
}
// O(n)
vector<int> getPi(pIter begin, pIter end) {
vector<int> pi(end - begin, 0);
int j = 0;
for (int i = 1; i < end - begin; i++) {
while (j > 0 && begin[i] != begin[j]) {
j = pi[j - 1];
}
if (begin[i] == begin[j]) {
pi[i] = ++j;
}
}
return pi;
}
int main() {
int program_cnt, min_virus;
int program_size;
cin >> program_cnt >> min_virus;
vector<program> programs(program_cnt);
for (int i = 0; i < program_cnt; i++) {
cin >> program_size;
programs[i].resize(program_size);
for (int j = 0; j < program_size; j++) {
cin >> programs[i][j];
}
}
pIter sub_start;
pIter sub_end;
// O(M - K + 1) * O(N) * O(M + K) = O(N * M * K)
for(int i = 0; i < programs[0].size() - min_virus + 1; i++) {
sub_start = programs[0].begin() + i;
sub_end = programs[0].begin() + i + min_virus;
// build pi
vector<int> pi = getPi(sub_start, sub_end);
bool contains = true;
for (int j = 1; j < program_cnt; j++) {
// 각 프로그램이 reverse포함해서 kmp 성립되는지 확인
bool success =
contains_virus(
programs[j].begin(),
programs[j].end(),
sub_start,
sub_end,
pi)
or
contains_virus(
programs[j].rbegin(),
programs[j].rend(),
sub_start,
sub_end,
pi);
if (!success) {
// cout << "failed at " << j << endl;
contains = false;
break;
}
}
if (contains) {
cout << "YES" << endl;
return 0;
}
}
cout << "NO" << endl;
}