时间:1s 空间:256M
题目描述:
老师给了小信 n 个只包含小写字母的字符串和一个数 k。每个字符串中,每种字母都只出现一次。
小信要从小写字母表(a-z)里选一些字母,且任意选择一些给定的字符串,使得选择的串里都恰好有 k 个字符串包含小信选的各个字母。请问他最多能选几个字母?
输入格式:
第一行包含两个整数 n,k,表示字符串数和给定的数。
接下来n行,每行包含一个只含小写字母的字符串。保证在每个字符串中,每种字母都只出现一次。
输出格式:
输出一个整数表示答案。
样例1输入:
4 2
acg
aef
abid
bcd
样例1输出:
4
样例2输入:
2 2
c
d
样例2输出:
0
约定与提示:
对于100%的数据,1≤n≤15,1≤k≤n。
样例1:选择字母 a,b,c,d,选择第 1, 3, 4个字符串,满足条件。
题意:
有n个字符串和一个数k,你要选择一些字符串和一些字母,这些字符串中的字母恰好有k个,求最多能选几个字母。
分析:
由题意得知,我们只要枚举选哪些字符串就可以了,看到数据1≤n≤15,就知道这是一道可以用指数级运算的题目,为了统计每个字符串中每个字符的数量,就要遍历26个字符,接下来就是dfs的模型了,
void dfs(int x){ dfs伪代码大致是这样。
if (x>n){
for (a->z){
if (数量为k)
++
}
max(res);
}
选取字母;
dfs(x+1);
回溯
dfs(x+1);
}
Code:
#include<bits/stdc++.h>
using namespace std;
long long n,x,y,a[2000005],top,l[2000005],r[2000005],ans;
int main(){
cin>>n>>x>>y;
for(long long i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
for(long long i=1;i<=n;i++){
if(a[i]>x||a[i]<y)
if(top&&!r[top])
r[top]=i-1;
if(a[i]<=x&&a[i]>=y)
if(top==0||r[top])
l[++top]=i;
}
if(!r[top])
r[top]=n;
for(long long i=1;i<=top;i++){
long long ll=l[i],rr=l[i],cx=0,cy=0;
if(a[ll]==x)cx++;
if(a[ll]==y)cy++;
while(ll<=r[i]){
if((!cx||!cy)&&rr<r[i]){
rr++;
if(a[rr]==x)cx++;
if(a[rr]==y)cy++;
}
else{
if(cx&&cy)
ans+=r[i]-rr+1;
if(a[ll]==x)cx--;
if(a[ll]==y)cy--;
ll++;
}
}
}
cout<<ans;
return 0;
}