Codeforces 808G. Anthem of Berland

G. Anthem of Berland

题意:给两串S,T。S由"a-z","?"组成,T由"a-z"组成。你可以钦定这些"?",询问 T 在 S 中最多出现次数。

 

想法:考虑Dp,需要记录的是匹配到 T 多长的前缀。于是设$F[i][j]$表示 S 前 j 位现匹配 T 前i位的最多完整匹配次数。转移需要求出$nx[i][v]$表示 T 前i位后面接上v能匹配的最长前缀,用KMP求一下。

Code

 

#include < cstdio >
#include < cstring >


#define gec getchar
#define FILE(F) freopen(F".in","r",stdin),freopen(F".out","w",stdout)
#define DEBUG fprintf(stderr,"Passing [%s] in Line (%d)\n",__FUNCTION__,__LINE__);

typedef long long ll;
template
inline void read(T&x)
{
	x=0;bool f=0;char c=gec();
	for(;c<'0'||c>'9';c=gec())f=(c=='-');
	for(;c>='0'&&c<='9';c=gec())x=x*10+c-'0';
	x=f?-x:x;
}

const int MAXN(100010);
int lengs,lengt,Ans;
char t[MAXN],s[MAXN];
namespace KMP
{
	int next[MAXN],nx[MAXN][26];
	void Kmp()
	{
		int j=0;next[1]=0;
		for(int i=2;i<=lengt;i++)
		{
			while(j&&(t[i]!=t[j+1]||j==lengt))j=next[j];
			if(t[i]==t[j+1])j++;
			next[i]=j;
		}
		for(int i=0;i<=lengt;i++)
		{
			for(int v=0;v<26;v++)
			{
				int j=i;
				while(j&&(v!=t[j+1]-'a'||j==lengt))j=next[j];
				if(v==t[j+1]-'a')j++;
				nx[i][v]=j;
			}
		}
	}
	
}using namespace KMP;

namespace DP
{
	int N,M;
	int max(int a,int b){return a>b?a:b;}
	void Dp()
	{
		N=lengt+10; M=lengs+10;
		int F[N][M]; memset(F,128,sizeof(F));
		F[0][0]=0;
		for(int j=0,Nex;j<lengs;j++)
		{
			for(int i=0;i<=lengt;i++)
			{
				if(F[i][j]<0)continue;
				if(s[j+1]=='?')
				for(int v=0;v<26;v++)
				{
					Nex=nx[i][v];
					F[Nex][j+1]=max(F[Nex][j+1],F[i][j]+(Nex==lengt));
				} else
				{
					Nex=nx[i][s[j+1]-'a'];
					F[Nex][j+1]=max(F[Nex][j+1],F[i][j]+(Nex==lengt));					
				}
			}
		}
		for(int i=0;i<=lengt;i++)Ans=max(Ans,F[i][lengs]);
	}
	
}using namespace DP;

int main()
{
#ifndef ONLINE_JUDGE
	FILE("C");
#endif		
	scanf("%s",s+1);lengs=strlen(s+1);
	scanf("%s",t+1);lengt=strlen(t+1);
	if(lengt>lengs){printf("0\n");return 0;}
	Kmp(); 	Dp();
	printf("%d\n",Ans);
	return 0;
}

突然迷恋 namespace

posted @ 2017-06-21 22:01  Oncle_Ha  阅读(790)  评论(0编辑  收藏  举报