题目链接:http://codeforces.com/contest/1303/problem/E
题目大意:
给你一个字符串S和一个字符串T。问能不能在S中找到一个子序列S1,然后从S中删除S1.再去删除后的字符串T中再找一个子序列S2。然后用S1+S2拼接成T。

思路:我们枚举T的分割点。进行dp。dp[i][j]:表示前i个字符和t1匹配到第j个字符时。能和t2匹配的最大长度。如果dp[|s|][|t1|]==|t2|就可行。注意t1和t2可能一个为空。特判就可以了。

#include <bits/stdc++.h>
#define LL long long
using namespace std;

int dp[500][500];

int check(char s[], char t1[], char t2[]){

    memset(dp, -1, sizeof(dp));
    int n=strlen(s+1), n1=strlen(t1+1), n2=strlen(t2+1);
    dp[0][0]=0;
    for(int i=1; i<=n; i++){
        dp[i][0]=0;
        for(int j=0; j<=n1; j++){
            if(s[i]==t1[j]){
                dp[i][j]=max(dp[i][j], dp[i-1][j-1]);//t1匹配数+1,但是t2的匹配数没有变化
            }
            if(dp[i-1][j]<n2&&s[i]==t2[dp[i-1][j]+1]){//t2匹配数+1,t1的匹配数没有变化
                dp[i][j]=max(dp[i][j], dp[i-1][j]+1);
            }
            dp[i][j]=max(dp[i][j], dp[i-1][j]);//前缀和最大值
        }
    }
    int ans=dp[n][n1];
    if(ans==n2){
        return 1;
    }
    else{
        return 0;
    }
}


int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        char s[500]={0}, t[500]={0}, t1[500]={0}, t2[500]={0};
        scanf("%s%s", s+1, t+1);
        int n=strlen(t+1), f=0;
        int tot=1;
        for(int i=1; i<=strlen(s+1); i++){//t1, t2为空特判
            if(s[i]==t[tot]){
                tot++;
            }
            if(tot==n+1){
                f=1;
                break;
            }
        }
        if(f){
            printf("YES\n");
            continue;
        }

        for(int len=1; len<=n-1; len++){
            for(int i=1; i<=len; i++){
                t1[i]=t[i];
            }
            for(int i=len+1; i<=n; i++){
                t2[i-len]=t[i];
            }
            t1[len+1]=t2[n-len+1]=0;
            if(check(s, t1, t2)){
                printf("YES\n");
                f=1;
                break;
            }
        }
        if(f==0){
            printf("NO\n");
        }
    }

    return 0;
}