【CF1550E】Stringforces

题目

题目链接:http://codeforces.com/problemset/problem/1550/E
\(s\) 是一个由前 \(k\) 个小写字母构成的字符串,\(v\) 是前 \(k\) 个小写字母中的某一个。定义 \(\mathrm{MaxLen}(s,v)\) 表示 \(s\) 所有仅由字母 \(v\) 构成的连续子串的最长长度。
定义 \(s\) 的价值为所有 \(\mathrm{MaxLen}(S,v)\) 的最小值,其中 \(v\) 取遍前 \(k\) 个小写字母。
现在给定一个长度为 \(n\) 的字符串 \(s\)\(s\) 中字母要么是前 \(k\) 个小写字母中的某一个,要么是问号。你需要将 \(s\) 中的每一个问号替换成前 \(k\) 个小写字母中的一个,并最大化 \(s\) 的价值。方便起见,你只需要输出这个最大的价值即可。
\(1\leq n\leq 2\times 10^5\)\(1\leq k\leq 17\)

思路

这个 \(k\leq 17\) 很明显在提示状压。
二分答案,设 \(f[i]\) 表示状态 \(i\) 里面所有字符都已经至少存在一个长度为 \(mid\) 的子串,最少需要覆盖掉 \(s\) 前多少个字符。
预处理出 \(\text{nxt}[i][j]\) 表示从字符串第 \(i\) 个字符起,要塞下连续 \(mid\) 个字符 \(j\),末尾最小会到达哪里。转移时考虑刷表,枚举不在集合 \(i\) 中的一个元素 \(j\),那么

\[f'[i\cup j]=\min(f[i\cup j],\text{nxt}[f[i]+1][j]) \]

最后判断一下 \(f[2^m-1]\) 是否 \(\leq n\) 即可。
时间复杂度 \(O((nk+2^kk)\log n)\)

代码

/*
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
*/
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int N=200010,M=19;
int n,m,lim,cnt[N][M],nxt[N][M],f[1<<M];
char s[N];

int main()
{
	scanf("%d%d%s",&n,&m,s+1);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			cnt[i][j]=cnt[i-1][j]+(s[i]-'a'+1==j);
	int l=0,r=n/m,mid;
	while (l<=r)
	{
		memset(f,0x3f3f3f3f,sizeof(f));
		memset(nxt,0x3f3f3f3f,sizeof(nxt));
		f[0]=0; lim=(1<<m);
		mid=(l+r)>>1;
		for (int i=n-mid+1;i>=1;i--)
		{
			int c=0;
			for (int j=1;j<=m;j++)
				if (cnt[i+mid-1][j]-cnt[i-1][j])
				{
					if (c) { c=-1; break; }
					c=j;
				}
			for (int j=1;j<=m;j++)
				if (!c || c==j) nxt[i][j]=i+mid-1;
					else nxt[i][j]=nxt[i+1][j];
		}
		for (int i=0;i<lim;i++)
			for (int j=1;j<=m;j++)
				if (!(i&(1<<j-1)) && f[i]<=n && nxt[f[i]+1][j]<=n)
					f[i|(1<<j-1)]=min(f[i|(1<<j-1)],nxt[f[i]+1][j]);
		if (f[lim-1]<=n) l=mid+1;	
			else r=mid-1;
	}
	cout<<l-1;
	return 0;
}
posted @ 2021-09-07 11:32  stoorz  阅读(33)  评论(0编辑  收藏  举报