首页 > 其他分享 >CF808G Anthem of Berland

CF808G Anthem of Berland

时间:2022-12-19 23:33:37浏览次数:64  
标签:Berland int Anthem GetC char cdot mathcal include CF808G

\(\mathcal Link\)

大概知道两种 DP 方法。(\(n\log n\) 做法太神了)

方法一:

设 \(f_i\) 表示 \(t\) 在 \(s[1\cdots i]\) 最多出现次数。当最后一位不会被匹配时,答案为 \(f_{i-1}\),否则设答案为 \(g_i\)。考虑下一次出现的位置,要么在 \(i-m+1\) 之前,要么是满足 \([i-m+1\cdots j]=[2i-m-j+1,i]\) 的位置,直接跳 next 即可。
\(f_i=\max\{f_{i-1},g_i\}\)
\(g_i=\max\{f_{i-m},g_{j}+1\}\)

复杂度 \(\mathcal O(|s|\cdot|t|)\)

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
char buf[1<<14],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
	x=0;int w=0;char c=GetC();
	for(;!isdigit(c);w|=c=='-',c=GetC());
	for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
	if(w) x=-x;
	return in;
}
const int N=1e5+5,inf=1e9;
char s[N],t[N];
int nxt[N];
int f[N],g[N];
int n,m;
bool check(int i,int j=1){
	for(int x=0;x<m;++x){
		if(s[i+x]!=t[j+x]&&s[i+x]!='?') return false;
	}
	return true;
}
int main(){
	scanf("%s%s",s+1,t+1);
	n=strlen(s+1),m=strlen(t+1);
	int j=0;
	for(int i=2;i<=m;++i){
		while(j&&t[j+1]!=t[i]) j=nxt[j];
		if(t[j+1]==t[i]) ++j;
		nxt[i]=j;
	}
	for(int i=m;i<=n;++i){
		g[i]=-inf;
		if(check(i-m+1)){
			g[i]=f[i-m]+1;
			for(int j=nxt[m];j;j=nxt[j]){
				g[i]=max(g[i],g[i-(m-j)]+1);
			}
		}
		f[i]=max(f[i-1],g[i]);
	}
	printf("%d\n",f[n]);
	return 0;
}

方法二:

设 \(dp_{i,j}\) 表示当主串指针为 \(i\),模式串指针为 \(j\) 时的最大出现次数。

对于 ? 枚举填什么。

转移时用 KMP 自动机 实现即可。复杂度 \(\mathcal O(|s|\cdot |t| \cdot |\Sigma|)\)

标签:Berland,int,Anthem,GetC,char,cdot,mathcal,include,CF808G
From: https://www.cnblogs.com/pref-ctrl27/p/16993375.html

相关文章

  • Codeforces 1 C. Ancient Berland Circus
    题意:二维平面中,给定三个点,这三个点是正多边形的三个顶点,求正多边形最小的面积。思路:两对点分别求中垂线,相交点是多边形外接圆的圆心,圆心有了半径和角度也就有了,之后求一......
  • CF1C Ancient Berland Circus
    给定\(3\)个点,求以这\(3\)个点为顶点的正多边形面积最小值。先以这张图为例,首先可以肯定圆的半径是确定的。根据秦九韶公式,有\(S_{\triangleABC}=\sqrt{p(p-a)(p......
  • CF808G Anthem of Berland
    给定\(s\)和\(t\),其中\(s\)中有\(k\)个?,求\(s\)补齐?后匹配\(t\)的最大次数。\(|s|\times|t|\leq10^7\)。先用一组数据\(HACK\)掉贪心做法:(贪心只......