CF1363F Rotating Substrings(dp)

这题的rotate操作其实就是暗示可以把某一个数提到最前面

因此本题其实就是求取最长公共子序列

但是有个问题当转移遇到s[i]==t[j]的时候,不能直接转移,因为只有当他二十六个字母的后缀数组全部比t串大时才可以转移,否则如果匹配了当前两个

没有办法把后面的提上来变成相等

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+10;
typedef long long ll;
int suffixa[2020][26];
int suffixb[2020][26];
int f[2010][2010];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        for(int i=0;i<=n;i++){
            for(int j=0;j<26;j++){
                suffixa[i][j]=0;
                suffixb[i][j]=0;
            }
        }
        for(int i=0;i<=n;i++){
            for(int j=0;j<=n;j++)
                f[i][j]=0;
        }
        int i;
        string s,t;
        cin>>s>>t;
        s=" "+s;
        t=" "+t;
        string tmp1=s;
        string tmp2=t;
        sort(tmp1.begin(),tmp1.end());
        sort(tmp2.begin(),tmp2.end());
        if(tmp1!=tmp2){
            cout<<-1<<endl;
            continue;
        }
        for(i=(int)s.size()-1;i>0;i--){
            for(int j=0;j<26;j++){
                suffixa[i][j]=suffixa[i+1][j];
                suffixb[i][j]=suffixb[i+1][j];
            }
            suffixa[i][s[i]-'a']++;
            suffixb[i][t[i]-'a']++;
        }
        for(i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                f[i][j]=max(f[i][j],max(f[i-1][j],f[i][j-1]));
                if(s[i]==t[j]){
                    int jj;
                    int sign=0;
                    for(jj=0;jj<26;jj++){
                        if(suffixa[i][jj]<suffixb[j][jj]){
                            sign=1;
                            break;
                        }
                    }
                    if(!sign)
                        f[i][j]=max(f[i][j],f[i-1][j-1]+1);
                }
            }
        }
        //cout<<"aa"<<" "<<f[n][n]<<endl;
        cout<<n-f[n][n]<<endl;
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/13233173.html