Educational Codeforces Round 82 (Rated for Div. 2)E(DP,序列自动机)

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 char s[407],t[407];
 5 int n,m;
 6 int nex[407][37];//nex[i][j]表示i位置以字母j+'a'最先出现的位置
 7 int dp[407][407];//把t分割为t1和t2,dp[i][j]表示t1长度为i,t2长度为j时,在字符串s中的最小位置
 8 int check(int x){
 9     int y=m-x;
10     dp[0][0]=0;
11     for(int i=0;i<=x;++i)
12         for(int j=0;j<=y;++j){
13             if(i==0&&j==0)
14                 continue;
15             dp[i][j]=1+n;
16             if(i&&dp[i-1][j]<n)//如果t1长度为i-1,t2长度为j,此时s还没有到达n,可以在当前情况让t1向后添加一个字母,更新dp[i][j]为添加后的答案与原本答案取最小值
17                 dp[i][j]=min(dp[i][j],nex[dp[i-1][j]][t[i]-'a']);
18             if(j&&dp[i][j-1]<n)//如果t2长度为j-1,t1长度为i,此时s还没有达到n,可以在当前情况让t2向后添加一个字母,更新dp[i][j]为添加后的答案与原本答案取最小值,两次取最小值后得到dp[i][j]的最优情况(从dp[i-1][j]推化而来还是从cp[i][j-1]推化而来)
19                 dp[i][j]=min(dp[i][j],nex[dp[i][j-1]][t[x+j]-'a']);
20         }
21     return dp[x][y]<=n;//如果t字符串能被分割为长度为x和y的两个字符串并且在s中长度不超过n那么就可以如此分割
22 }
23 int main(){
24     ios::sync_with_stdio(false);
25     cin.tie(NULL);
26     cout.tie(NULL);
27     int T;
28     cin>>T;
29     while(T--){
30         cin>>s+1>>t+1;
31         n=strlen(s+1);
32         m=strlen(t+1);
33         for(int i=0;i<26;++i)
34             nex[n][i]=1+n;
35         for(int i=n;i;--i){
36             for(int j=0;j<26;++j)
37                 nex[i-1][j]=nex[i][j];
38             nex[i-1][s[i]-'a']=i;
39         }
40         int flag=0;
41         for(int i=1;i<=m;++i)
42             if(check(i)){
43                 cout<<"YES\n";
44                 flag=1;
45                 break;
46             }
47         if(!flag)
48             cout<<"NO\n";
49     }
50     return 0;
51 }

猜你喜欢

转载自www.cnblogs.com/ldudxy/p/12308581.html