【ICPC】2022西安站 G. Perfect Word | DP?

259 阅读2分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

【ICPC】2022西安站 G. Perfect Word | DP?

大规模问题转化为相同的小规模问题,勉强算是 DP 吧……

题目链接

Problem - G - Codeforces

题目

image.png

题目大意

给出 nn 个字符串,要求你找到最长的完美单词的长度。

字符串 TT 被称为完美单词,当且仅当 TT 的每个非空子串都出现在给出的字符串中。

字符串 SS 被称为 TT 的子串,当且仅当它可以通过从 TT 的开头或结尾删除几个(可能为零)字符来获得。

思路

容易发现在所有给出的字符串中:

  1. 长度为 1 的字符串一定是完美单词。
  2. 一个字符串 S={s1,s2,...,sn}S=\{s_1,s_2,...,s_n\},若 {s2,s3,...,sn}\{s_2,s_3,...,s_n\}{s1,s2,...,sn1}\{s_1,s_2,...,s_{n-1}\} 都是完美单词,那么 S 就是完美单词。
  3. 不满足上述两种情况的单词一定不是完美单词。

第一条显然,让我们来分析一下第二条。

对于一个字符串 S=s1,s2,...,snS={s_1,s_2,...,s_n},若

s2,s3,...,sns1,s2,...,sn1s_2,s_3,...,s_n\\ s_1,s_2,...,s_{n-1}\\

都是完美单词,那么 S 就是完美单词。

观察下图,容易发现:

image.png

SS 里所有以 s1s_1 开头,以 si,i[1,n1]s_i,i\in[1,n-1] 结尾的子串都会被 {s1,s2,...,sn1}\{s_1,s_2,...,s_{n-1}\} 判断到,所有不以 s1s_1 开头,以 si,i[1,n]s_i,i\in[1,n] 结尾的子串都会被 {s1,s2,...,sn1}\{s_1,s_2,...,s_{n-1}\} 判断到。

除此之外唯一没被判断到的以 s1s_1 开头 sns_n 结尾的字符串就是本身。

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