P3426 [POI2005] SZA-Template 题解
题意:
给定一个字符串,求能盖出这个字符串的印章的最小长度。
分析:
显然,这个印章一定是 的 border。
记 表示盖满前 个的最小印章大小,那么答案只可能为 ,或者 。
证明如下:
- 显然答案为 是整个字符串。
- 由于 的 border 可以拆分成两部分,即 的 border 与 本身, 均有。
现在只剩一个问题,什么时候 成立呢?
对于两个相交的串 ,如果它们均能被 盖出,那么 一定能被 盖出。因为印章只可能为 ,因此一定能盖出。
由于 能盖出 ,那么它也一定能盖出 ,于是如果 最远能盖到 及以后,那么就一定能盖完 。
于是我们再记 表示前缀 作为印章时最远能盖到的位置,然后直接转移即可。
代码:
#include<bits/stdc++.h>
#define int long long
#define N 500005
using namespace std;
int n;
int kmp[N], dp[N], h[N];
string s;
signed main() {
cin >> s;
n = s.length();
s = " " + s;
int j = 0;
for(int i = 2; i <= n; i++) {
while(j && (s[j + 1] != s[i])) j = kmp[j];
if(s[j + 1] == s[i]) j++;
kmp[i] = j;
}
for(int i = 1; i <= n; i++) {
dp[i] = i;
if(h[dp[kmp[i]]] >= i - kmp[i]) dp[i] = dp[kmp[i]];
h[dp[i]] = i;
}
cout << dp[n];
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】