CF R 635 div1 C KaaviおよびMagic Spell間隔dp

リンク:KaaviとMagic Spell

彼がそのような料理を持っていることに気づくのに、ダースCFしかかかりませんでした。

dp f [i] [j]が最初のi文字がTの最初のj文字と一致するスキームの数を表す場合、遷移は非常に面倒になり、状態遷移は一度にO(n)になります。

タイムアウトになり、この状態の遷移も正しくありません。現在のS文字列の後に一致しないものがある可能性がありますが、現時点では反映できません。

では、一度に1文字ずつ追加し、Tと照合する状態をどのように説明すればよいでしょうか。

S文字列のiの対応するTの位置を列挙して、dpが

f [i] [j] [k]は、最初のi文字がTのj〜k区間の解の数と一致するため、今のところ問題がないことを意味します。

ただし、重複したスキームが存在するため、この状態はまだ不可能です。

2つのスキームの重複が列挙されているために、以前の状態が繰り返される理由について慎重に検討してください。

最終的な回答の解の数を考慮すると、点iの位置が固定されていないことを見つけることは難しくありません。

単純に1の位置を列挙してから、上記の間隔dpを実行できます。

このように、全体としてチームの右に追加する問題はなく、状態数の重複の問題もありません。

ステートフルf [i] [j]は、最初のj-i + 1文字がTに一致する、区間i〜jの解の数を表します。

転送を検討してください。

j-i + 2文字目は転送可能かどうか判断できます。

毎回使用される文字は固定されているため、列挙の決定は必要ありません。

したがって、複雑さはn ^ 2です。

const int MAXN=3010;
int T,n,ans,m;
int f[MAXN][MAXN];
char a[MAXN],b[MAXN];
int main()
{
	freopen("1.in","r",stdin);
	gc(a);gc(b);
	n=strlen(a+1);
	m=strlen(b+1);
	rep(1,n,i)if(a[1]==b[i]||i>m)f[i][i]=1;
	for(int len=2;len<=n;++len)
	{
		for(int i=1;i<=n-len+1;++i)
		{
			int j=i+len-1;
			if(a[len]==b[i]||i>m)f[i][j]=(f[i][j]+f[i+1][j])%mod;
			if(a[len]==b[j]||j>m)f[i][j]=(f[i][j]+f[i][j-1])%mod;
		}
	}
	rep(m,n,i)ans=(ans+f[1][i])%mod;
	put(ans*2%mod);
	return 0;
}

おすすめ

転載: www.cnblogs.com/chdy/p/12717344.html