本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【ICPC】2022西安站 G. Perfect Word | DP?
大规模问题转化为相同的小规模问题,勉强算是 DP 吧……
题目链接
题目
题目大意
给出 个字符串,要求你找到最长的完美单词的长度。
字符串 被称为完美单词,当且仅当 的每个非空子串都出现在给出的字符串中。
字符串 被称为 的子串,当且仅当它可以通过从 的开头或结尾删除几个(可能为零)字符来获得。
思路
容易发现在所有给出的字符串中:
- 长度为 1 的字符串一定是完美单词。
- 一个字符串 ,若 和 都是完美单词,那么 S 就是完美单词。
- 不满足上述两种情况的单词一定不是完美单词。
第一条显然,让我们来分析一下第二条。
对于一个字符串 ,若
都是完美单词,那么 S 就是完美单词。
观察下图,容易发现:
里所有以 开头,以 结尾的子串都会被 判断到,所有不以 开头,以 结尾的子串都会被 判断到。
除此之外唯一没被判断到的以 开头 结尾的字符串就是本身。
用 STL 里的 map 进行判断即可。
代码
队友的代码~
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct node {
string s;
int sz;
}a[100005];
unordered_map<string,int>mp;
void check(string s) {
string ss, now, sss;
now = s;
int l = s.size();
for( int j = 0; j < l - 1; j++) ss += now[j];
string ss1; ss1 += now[l-1];
for( int j = 1; j < l; j++) sss += now[j];
string ss2; ss2 += now[0];
if(l == 1) mp[s] = 1;
if(mp[sss] && mp[ss2] && mp[ss] &&mp[ss1]) mp[s] = 1;
}
int main(){
int n;
int ans = 0;
scanf("%d", &n);
for( int i = 1; i <= n; i++) {
string str;
cin >> str;
a[i].s = str;
a[i].sz = str.size();
}
sort(a + 1, a + n + 1, [](node xx, node yy) {
return xx.sz < yy.sz;
});
if(a[1].sz == 1) ans = 1;
for( int i = 1; i <= n; i++) {
string ss, now, sss;
now = a[i].s;
for( int j = 0; j < a[i].sz - 1; j++) ss += now[j];
string ss1; ss1 += now[a[i].sz-1];
for( int j = 1; j < a[i].sz; j++) sss += now[j];
string ss2; ss2 += now[0];
if(mp[sss] && mp[ss2] && mp[ss] &&mp[ss1]) ans = max(ans, a[i].sz);
check(now);
}
printf("%d", ans);
return 0;
}