cf 1337E - Kaavi and Magic Spell (区间DP)

题目:传送门

题意:给出两个字符串S和T, 和一个空字符串A, 每次将s的第一个字符放在A的前面或后面 ;求 A串 在这样的过程中 ,其前缀等于T的方法数 (若S=T=“a” , 字符‘a’可以往空串前插也可以后插,故是两种方法)

  设 dp(i,l,r) 表示 S串中的前i个字符 形成的字符串与 T串中的 [ l , r ] 完全匹配的方法数 ,由于 i 个字符形成的字符串长度为 i ,所以一定有 r-l+1 == i 。因此,dp(i,l,r) 可以简化为 dp(l,r) ;

  前缀等于T的A串 , 可以表示为 A = T + "??...?"('?'可以与任意字母匹配)  ,A串长度为n  、 T串长度为m; 上述的与T串匹配 可以看做: 前i个字符形成的字符串  与  满足题意的A串匹配

  1. 若 s[i] == t[l] , 则有 dp(l,r) = dp(l,r) + dp(l+1,r)  , 前插 s[i]   【 s[i] 与 t[l] 匹配 ;状态转移:前 i-1 个字符形成的字符串  (  i-1 == r-(l+1)+1  ) 与 t[ l+1 , r ] 的完全匹配  + 前插 s[i]  ==》 前 i=r-l+1 个字符形成的字符串与t[ l , r ] 的完全匹配   】

  2. 若   s[i] == t[r] , 则有 dp(l,r) = dp(l,r) + dp(l,r-1)   , 后插 s[i]   

  3. 若   l > m  ||  r > m  , 则有 dp(l,r) = dp(l,r) + dp(l,r-1) + dp(l+1,r)  【这里的 > m 指的是 与在A串中的“任意串”进行匹配, 既然是 “任意串” 那么前插后插都满足】

 

AC代码:(dp的预处理见代码注释)

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(2)
 3 using namespace std;
 4 typedef long long LL;
 5 typedef pair<int,int> pii;
 6 typedef pair<double,double> pdd;
 7 const int N=3e3+5;
 8 const LL inf=(1uLL<<63)-1;
 9 const LL mod=998244353;
10 const double eps=1e-9;
11 const long double pi=acos(-1.0L);
12 #define ls (i<<1)
13 #define rs (i<<1|1)
14 #define fi first
15 #define se second
16 #define pb push_back
17 #define mk make_pair
18 #define mem(a,b) memset(a,b,sizeof(a))
19 LL read()
20 {
21     LL x=0,t=1;
22     char ch;
23     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
24     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
25     return x*t;
26 }
27 char s[N],t[N];
28 LL dp[N][N];
29 int main()
30 {
31     scanf("%s%s",s+1,t+1);
32     int n=strlen(s+1),m=strlen(t+1);
33     for(int i=1;i<=n+1;i++) dp[i][i-1]=1;//dp[i][i]=dp[i][i-1]+dp[i+1][i]=2  (i,i-1)可以视为空串
34     for(int i=1;i<=n;i++)
35     {
36         for(int l=1,r=i;r<=n;l++,r++)
37         {
38             if(l>m||s[i]==t[l]) dp[l][r]+=dp[l+1][r],dp[l][r]%=mod;
39             if(r>m||s[i]==t[r]) dp[l][r]+=dp[l][r-1],dp[l][r]%=mod;
40         }
41     }
42     LL ans=0;
43     for(int i=m;i<=n;i++) ans+=dp[1][i],ans%=mod;
44     printf("%lld\n",ans);
45     return 0;
46 }
View Code

 

  

posted @ 2020-04-27 22:06  DeepJay  阅读(144)  评论(0编辑  收藏  举报