トピックポータル(内部タイトル140)
入力形式
最初の2行は、二つの文字列の同じ長さを有し、林Xiansen庭上の文字を説明しました。
第三行の文字列$ S $。
出力フォーマット
$ ^ 7 + 9 MODが可能ヘビの数、$ 10表す出力ライン整数。
サンプル
サンプル入力1:
rwby
ybwr
rwby
出力例1:
4
サンプル入力2:
OOO
OOO
OO
出力例2:
14
データ範囲とヒント
S | | \ $ N、$ 20 \%の$のデータについては、 leqslant 16 $。
データで$ 40 \%の$、$ nに対して、| S | \ leqslant 40 $。
S | | \ $ N、$ 60 \%の$のデータについては、 leqslant 200 $。
データ$、$ 1 $ \ 100%\ leqslant nの、| S | \ leqslant 2,000 $、 入力小文字の文字に含まれています。
問題の解決策
最初のパスのヘビのパスを考えてみましょう、それは三つの部分$ \ $下矢印次の図に分解することができます
その後、混沌(ライジング)を取り、その後、再び他の方向で$グリッドB $を取り、その後、戻ってきて、スネークは$ $グリッドを移動し、戻ってきて一方向に最初にされている必要があります。
同じではありませんが、ハッシュによって判断することができます。
次に$ DP $検討し、[J] [K] $点$(i、j)を示し、[I]] $ K $溶液の数に一致$を、$ DPを定義。
リングは、外側のループ$ K $が表示されない場合があります。
便宜上、1つの方向に行くようにデフォルトすることができます。そして、うまく再びピットイン全体フリップチャートを置きます。
注場合は、日本語文の長さのヘビ$ 1、$ 2 $ $が必要であること。
時間の複雑さ:$ \シータ(| S | ^ 2)$。
期待はスコア:$ $ 100ポイントを。
実際のスコア:$ $ 100ポイント。
コードの時間
#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
struct rec{int s,x,y;};
int a[2][2001],b[2001],n,s;
char ch[2001];
long long dp[2][2001][4001][2],ans;
unsigned long long hsh[2001],flag[2001]={1},has[2][2][2002];
unsigned long long ask(bool x,bool y,int l,int r){return y?has[x][y][r]-has[x][y][l+1]*flag[l-r+1]:has[x][y][r]-has[x][y][l-1]*flag[r-l+1];}
unsigned long long get(int l,int r){return hsh[r]-hsh[l-1]*flag[r-l+1];}
void work()
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
has[i][0][j]=has[i][0][j-1]*131+a[i][j];
for(int i=0;i<2;i++)
for(int j=n;j;j--)
has[i][1][j]=has[i][1][j+1]*131+a[i][j];
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
{
dp[i][j][1][0]=(a[i][j]==b[1]);
for(int k=2;k<=j;k++)
dp[i][j][k<<1][1]=(ask(i^1,1,j,j-k+1)==get(1,k))&&(ask(i,0,j-k+1,j)==get(k+1,k<<1));
}
for(int k=1;k<=s;k++)
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
{
if(a[i][j]!=b[k])continue;
dp[i][j][k][0]=(dp[i][j][k][0]+dp[i][j-1][k-1][0]+dp[i][j-1][k-1][1])%mod;
dp[i][j][k][1]=(dp[i][j][k][1]+dp[i^1][j][k-1][0])%mod;
}
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=s;k++)
{
int res=(s-k)>>1;
if(!((s-k)&1)&&res!=1&&(s==k||(j+res<=n&&ask(i,0,j+1,j+res)==get(k+1,k+res)&&ask(i^1,1,j+res,j+1)==get(s-res+1,s))))
ans=(ans+dp[i][j][k][0]+dp[i][j][k][1])%mod;
}
}
int main()
{
scanf("%s",ch+1);n=strlen(ch+1);
for(int i=1;i<=n;i++)a[0][i]=ch[i]-'a'+1;
scanf("%s",ch+1);
for(int i=1;i<=n;i++)a[1][i]=ch[i]-'a'+1;
scanf("%s",ch+1);s=strlen(ch+1);
for(int i=1;i<=s;i++)
{
b[i]=ch[i]-'a'+1;
flag[i]=flag[i-1]*131;
hsh[i]=hsh[i-1]*131+b[i];
}
work();
reverse(a[0]+1,a[0]+n+1);
reverse(a[1]+1,a[1]+n+1);
memset(dp,0,sizeof(dp));
work();
if(s==1)
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
ans-=(a[i][j]==b[1]);
}
if(s==2)
{
for(int i=0;i<2;i++)
for(int j=1;j<=n;j++)
ans-=(a[i][j]==b[1]&&a[i^1][j]==b[2]);
}
printf("%lld",ans);
return 0;
}
rp++