19 徐州網絡賽 M.Longest subsequence

傳送門

題意:給你指定長度的兩個字符串S和T,求出在S的子序列(可非連續)裏字典序大於T的子序列最長長度。

思路:求出每個位置後26個字母第一個出現的位置,存進二位數組nx[p][q]裏,p表示位置,q表示字母與'a'的差值(例如 q==1時,表示S字符串p位置後第一次出現'b'字符的下標)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;

int n,m;
char s[maxn],t[maxn];
int nx[maxn][26];
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s%s",s+1,t+1);
    for( int i=0; i<26; ++i)
    {
        nx[n][i]=nx[n+1][i]=n+1;
    }
    for( int i=n-1; i>=0; --i)//求下標
    {
        for( int j=0; j<26; ++j)
        {
            nx[i][j]=nx[i+1][j];
        }
        int to=s[i+1]-'a';
        nx[i][to]=i+1;
    }
    for( int i=0; i<n; i++)//檢驗下標正確行
    {
        bool f=0;
        for( int j=0; j<26; ++j)
        {
            if(!f)
            {
                printf("^^^^%d^^^^\n",i);
                f=1;
            }
            if(nx[i][j]!=n+1)
            {
                printf("%c %d %d\n",j+'a',j,nx[i][j]);
            }
        }
        puts("");
    }
    int res=-1,cur=0;
    for( int i=1; t[i]; ++i)//遍歷T字符串
    {
        int pos=t[i]-'a';
        printf("%d*\n",cur);
        for( int j=pos+1; j<26; ++j)//找到存在的大於t[i]的字符
        {
            int id=nx[cur][j];//找到其下標
            if(id<=n)
            {
                res=max(res,n-id+1+i-1);//有大的直接更新答案
                printf("%d %d %d ***\n",id,pos,res);
            }
        }
        cur=nx[cur][pos];
        if(cur>n)
            break;
    }
    if(cur<n)
        res=max(res,m+n-cur);
    printf("%d\n",res);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章