洛谷P1481 魔族密码(最长前缀链长度)
虽然怎么说呢,其实这题应该用来练字典树,但是我发现它作为最长前缀链长度挺板的,直接拿来当板子了,所以没用字典树
题目如下:
P1481 魔族密码
题目背景
风之子刚走进他的考场,就……
花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花)
风之子:我呕……(杀死人的眼神)快说题目!否则……-_-###
题目描述
花花:……咦好冷我们现在要解决的是魔族的密码问题(自我陶醉:搞不好魔族里面还会有人用密码给我和菜虫写情书咧,哦活活,当然是给我的比较多拉*_*)。
魔族现在使用一种新型的密码系统。每一个密码都是一个给定的仅包含小写字母的英文单词表,每个单词至少包含 \(1\) 个字母,至多 \(75\) 个字母。如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含,即前一个单词是后一个单词的前缀,则称词表为一个词链。例如下面单词组成了一个词链:
- \(\verb!i!\);
- \(\verb!int!\);
- \(\verb!integer!\)。
但下面的单词不组成词链:
- \(\verb!integer!\);
- \(\verb!intern!\)。
现在你要做的就是在一个给定的单词表中取出一些词,组成最长的词链,就是包含单词数最多的词链。将它的单词数统计出来,就得到密码了。
风之子:密码就是最长词链所包括的单词数阿……
输入格式
这些文件的格式是,第一行为单词表中的单词数 \(N\)(\(1 \le N \le 2000\)),下面每一行有一个单词,按字典顺序排列,中间也没有重复的单词。
输出格式
输出共一行,一个整数,表示密码。
输入输出样例 #1
输入 #1
5
i
int
integer
intern
internet
输出 #1
4
ac码:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ref(i,n,x) for(int i=x;i>=n;i--)
#define fo(i, n, x) for (int i = x; i <= n; i++)
int mod = 1e6 + 7;
void solve() {
int n;
cin>>n;
vector<string>s(n+1);
vector<int>a(n+1,1);
int ans=0;
fo(i,n,1){
cin>>s[i];
for(int j=i-1;j>=1;j--){
if(s[i].find(s[j])==0)a[i]=max(a[i],a[j]+1);
}
ans=max(ans,a[i]);
}
cout<<ans;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t=1;
//cin >> t;
while (t--) solve();
return 0;
}
点击查看代码
// 检查所有之前的字符串(j < i),看是否是当前字符串s[i]的前缀
for (int j = i - 1; j >= 1; --j) {
// s[i].find(s[j]) 是查找s[j]在s[i]中第一次出现的位置
// 如果返回0,说明s[j]从s[i]的第0个字符开始匹配,即s[j]是s[i]的前缀
if (s[i].find(s[j]) == 0) {
// 如果s[j]是s[i]的前缀,那么以s[i]结尾的序列长度,可以更新为
// “以s[j]结尾的序列长度 + 1”(因为可以在s[j]的序列后加一个s[i])
f[i] = max(f[i], f[j] + 1);
}
}

浙公网安备 33010602011771号