P9364题解
Nuyoah_awa · · 题解
题目大意
给定
求这些字符串中长度最长的「完美单词」的长度。
题目分析
首先来想暴力,枚举每一个字符串,判断其是否为「完美单词」,如果是,更新最长长度。
看似上述算法的时间复杂度是
但是我们可以发现,对于一个「完美单词」,他最多需要
但是最多只有
再说一些细节:
- 我们可以从长度较长的字符串开始判断,这样第一个「完美单词」一定是最长的。
- 我们可以写一个
\operatorname{check} 函数,每回发现没出现过的子串时,就说明这个字符串一定不是「完美单词」,后面的子串也就没必要判断了。 - 我们可以把所有的字符串丢进一个
\operatorname{map} 里面,这样就可以实现\mathcal O(\log n) 判断是否出现过了。 - 我们可以使用
\operatorname{substr} 来枚举子串,加上\operatorname{map} 判断,总的判断效率仍然是\mathcal O(\log n) 的。
code
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
int n;
string s[N];
map <string, bool> mp;
bool cmp(string u, string v)
{
return u.size() > v.size();
}
bool check(string s)
{
for(int i = s.size() - 2;i >= 1;i--)
for(int j = 1;j + i <= s.size();j++)
if(mp[s.substr(j, i)] == false)
return false;
return true;
}
signed main()
{
scanf("%d", &n);
for(int i = 1;i <= n;i++)
{
cin >> s[i];
mp[s[i]] = true;
s[i] = "#" + s[i];
}
sort(s + 1, s + n + 1, cmp);
for(int i = 1;i <= n;i++)
{
if(check(s[i]))
{
printf("%d", s[i].size() - 1);
return 0;
}
}
return 0;
}