zoukankan      html  css  js  c++  java
  • 2019 徐州网络赛 M Longest subsequence t

    对于答案来说,一定是

    1. 前 i-1 个字符和 t的前 i 个一样,然后第 i 个字符比 t的 大 (iin [1,m])
    2. 前缀为t,然后长度比t长

    对于第一种情况,枚举这个 i ,然后找最小的 p 可以使得从(s[1sim p]) 中产生(t_1t_2cdots t_{i-1}) ,然后在(s[p+1,n])中找最左边的比(t[i]) 大的字符,假如 找到了(s[pos]),那么后面的(s[pos+1,n]) 都可以加到答案后面(因为(s[pos] > t[i]) 已经保证答案大于t了)

    对于第二种,根据求第一种的方法,不难求出

    如何找最小的p?预处理一个(sf[i][c]) 数组,表示(s[i]) 后面第一个字符(c)在哪里即可

    如何找pos? 也是用预处理的数组循环最多26次即可

    复杂度(O(n*26))

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6+10;
    int sf[N][26];
    
    char s[N],t[N];
    
    int n,m;
    int main(){
        scanf("%d%d",&n,&m);
        scanf("%s%s",s+1,t+1);
        for(int i=0;i<26;i++)sf[n][i] = n+1;
    
        for(int i=n-1;i>=0;i--){
            memcpy(sf[i],sf[i+1],sizeof sf[i]);
            sf[i][s[i+1]-'a'] = i+1;
        }
    
        int p = 0,res = -1;
        for(int i=1;i<=m;i++){
            int pos = n+1;
            for(int j=t[i]-'a'+1;j<26;j++){
                pos = min(pos,sf[p][j]);//找到最近的那个s[pos] > t[i];
            }
            if(pos != n+1)
                res = max(res,i+n-pos);//(n-pos)为后面还可以加的长度
            p = sf[p][t[i]-'a'];
            if(p == n+1)break;
        }
        if(p < n)
            res = max(res,n-p+m);
        printf("%d
    ",res);
        return 0;
    }
    
  • 相关阅读:
    CF 461B Appleman and Tree
    POJ 1821 Fence
    NOIP 2012 开车旅行
    CF 494B Obsessive String
    BZOJ2337 XOR和路径
    CF 24D Broken robot
    POJ 1952 BUY LOW, BUY LOWER
    SPOJ NAPTIME Naptime
    POJ 3585
    CF 453B Little Pony and Harmony Chest
  • 原文地址:https://www.cnblogs.com/1625--H/p/11482455.html
Copyright © 2011-2022 走看看