这道题一眼就是动态规划,然而貌似并不好做。
如果不转换模型,状态是难以处理的。
巧妙地转化:不直接求一种字母头尾距离,而是拆开放到状态中。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=5010; 6 char s1[maxn],s2[maxn]; 7 int B1[26],E1[26],B2[26],E2[26]; 8 int dp[maxn][maxn]; 9 int add[maxn][maxn]; 10 int main(){ 11 int T,len1,len2; 12 scanf("%d",&T); 13 while(T--){ 14 scanf("%s",s1+1); 15 scanf("%s",s2+1); 16 len1=strlen(s1+1); 17 len2=strlen(s2+1); 18 memset(B1,127,sizeof(B1)); 19 memset(E1,-1,sizeof(E1)); 20 memset(B2,127,sizeof(B2)); 21 memset(E2,-1,sizeof(E2)); 22 for(int i=1;i<=len1;i++){ 23 s1[i]-='A'; 24 if(B1[s1[i]]>len1)B1[s1[i]]=i; 25 E1[s1[i]]=i; 26 } 27 28 for(int i=1;i<=len2;i++){ 29 s2[i]-='A'; 30 if(B2[s2[i]]>len2)B2[s2[i]]=i; 31 E2[s2[i]]=i; 32 } 33 34 for(int i=0;i<=len1;i++) 35 for(int j=0;j<=len2;j++){ 36 if(i==j&&i==0)continue; 37 if(!i||j&&dp[i][j-1]+add[i][j-1]<=dp[i-1][j]+add[i-1][j]){ 38 dp[i][j]=dp[i][j-1]+add[i][j-1]; 39 add[i][j]=add[i][j-1]; 40 if(B2[s2[j]]==j&&B1[s2[j]]>i) 41 add[i][j]++; 42 if(E2[s2[j]]==j&&E1[s2[j]]<=i) 43 add[i][j]--; 44 } 45 if(!j||i&&dp[i][j-1]+add[i][j-1]>dp[i-1][j]+add[i-1][j]){ 46 dp[i][j]=dp[i-1][j]+add[i-1][j]; 47 add[i][j]=add[i-1][j]; 48 if(B1[s1[i]]==i&&B2[s1[i]]>j) 49 add[i][j]++; 50 if(E1[s1[i]]==i&&E2[s1[i]]<=j) 51 add[i][j]--; 52 } 53 } 54 printf("%d ",dp[len1][len2]); 55 } 56 return 0; 57 }