• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

RomanLin

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【Z函数】codeforces 2010 C2. Message Transmission Error (hard version)

前言

Z 函数的定义

对于一个字符串 \(s\),定义 Z 函数 \(Z[i]\) 为以 \(s[i]\) 为起始位置的后缀与整个字符串 \(s\) 的最长公共前缀的长度。

Z 函数的应用

  1. 字符串匹配问题

题目

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;
}

posted on 2024-12-16 19:17  RomanLin  阅读(52)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3