前言
Z 函数的定义
对于一个字符串 \(s\),定义 Z 函数 \(Z[i]\) 为以 \(s[i]\) 为起始位置的后缀与整个字符串 \(s\) 的最长公共前缀的长度。
Z 函数的应用
- 字符串匹配问题
题目
https://codeforces.com/problemset/problem/2010/C2
题意
给定一个字符串 \(s\),若其可以找到真前缀 \(s_1\) 和真后缀 \(s_2\),满足二者相等且存在一个长度大于 \(0\) 的字符串 \(sub\) 既是 \(s_1\) 的后缀,也是 \(s_2\) 的前缀。
若存在,输出 \(YES\) 并换行输出字符串 \(s_1\),否则输出 \(NO\)。
题解
对于条件“存在一个长度大于 \(0\) 的字符串 \(sub\) 既是 \(s_1\) 的后缀,也是 \(s_2\) 的前缀”,只需要枚举的长度满足大于字符串 \(s\) 的一半即可。
对于条件“真前缀 \(s_1\) 和真后缀 \(s_2\) 相等”,可以用 Z 函数判断 \(s_1 == s_2\) 是否成立。从而达到 \(O(n)\) 时间复杂度枚举出全部情况。
参考代码
#include<bits/stdc++.h>
using namespace std;
string s;
int n, m;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> s;
n = s.size();
m = n / 2 + 1;
vector<int> z(n);
z[0] = n;
for (int i = 1, l, r = 0; i < m; ++ i) {
if (i <= r) z[i] = min(z[i - l], r - i);
while (s[z[i]] == s[z[i] + i]) ++ z[i];
if (i + z[i] > r) l = i, r = i + z[i];
if (z[i] >= m && r == n) {
cout << "YES\n" << s.substr(0, z[i]);
return 0;
}
}
cout << "NO\n";
return 0;
}
标签:前缀,Transmission,hard,codeforces,后缀,int,字符串,函数
From: https://www.cnblogs.com/RomanLin/p/18606817