[CSP-S Simulation Test]: snake (the DP + + hash configuration)

Topic Portal (internal title 140)


Input Format

  The first two rows have the same length of the two strings, the letters on the Lin Xiansen garden described.
  A third line string $ S $.


Output Format

  Output line an integer representing the number of possible snake, $ 10 to $ ^ 7 + 9 mod.


Sample

Sample input 1:

rwby
ybwr
rwby

Sample output 1:

4

Sample input 2:

ooo
ooo
oo

Sample Output 2:

14


Data range and tips

  For $ 20 \% $ data, $ n, | S | \ leqslant 16 $.
  Data for $ 40 \% $ in, $ n, | S | \ leqslant 40 $.
  For $ 60 \% $ data, $ n, | S | \ leqslant 200 $.
  Data for $ 100 \% of $, $ 1 \ leqslant n, | S | \ leqslant 2,000 $, included in the input lowercase letters.


answer

Consider first path snake path, it can be disassembled into three parts $ \ $ DownArrow following figures

Snake must have been first in one direction to go $ a $ grid, and then come back; then take the chaos (writhing), and then again take the $ b $ grid in the other direction, and then come back.

Not the same as can be judged by the hash.

Then consider $ DP $, defined $ dp [i]] [j] [k] $ denotes the point $ (i, j) $, matched to the number of $ k $ solution.

Ring may prevent the outer loop $ k $ appears.

For convenience, you can default to go in one direction; then put the whole flip chart pitted again just fine.

Note that the case requires Japanese sentence length snake $ 1 and $ 2 $ a $.

Time complexity: $ \ Theta (| S | ^ 2) $.

Expectations score: $ 100 $ points.

Actual score: $ 100 $ points.


Code time

#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++

Guess you like

Origin www.cnblogs.com/wzc521/p/11830973.html