“一切都会|

zplqwq

园龄:3年10个月粉丝:25关注:14

2022-06-21 17:30阅读: 36评论: 0推荐: 0

题解 P1666 前缀单词

这道题我们考虑dp。

dpi 表示以 si 结尾的满足条件的子集个数。

例如在样例中,dp1 就是 1 ,因为以 hello 为结尾且满足条件的子集数只有它本身。

初始条件是 dpi=i ,因为无论如何,自己本身永远都是安全的。

接下来转移就是显然的:

dpj=dpi 当且仅当 si,sj 可以共存。

如何判断能否共存的?

用这个引理:

把这些字符串排序后,对于任意一组 j<i 且他们不互为前缀,则对于任意一组 k<j 且他们不互为前缀,则 ki 不互为前缀。

注意,这里排序是必须的,否则他会把一些不符合条件的子集算进去。

答案显然就是所有 dpi 的和再加一。因为空集也算。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
const int N=2010;
string s[N];
int dp[N];
int ans;
bool check[N][N];
bool pd(int i,int j)
{
if(s[i].size() < s[j].size()) swap(i,j);
return s[i].find(s[j])!=0;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>s[i];
sort(s+1,s+1+n);
for(int i=1;i<=n;i++)
{
dp[i]=1;
for(int j=1;j<=n;j++)
{
check[i][j]=pd(i,j);
}
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(check[i][j]==1)dp[j]+=dp[i];
}
}
for(int i=1;i<=n;i++)
{
ans+=dp[i];
//cout<<dp[i]<<endl;
}
cout<<ans+1<<endl;
return 0;
}

本文作者:zplqwq

本文链接:https://www.cnblogs.com/zplqwq/p/16397658.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   zplqwq  阅读(36)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示