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 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)