2019年 ACM/ICPC 亞洲區域賽(徐州)網絡賽M.Longest subsequence(思維+貪心)

String is a very useful thing and a subsequence of the same string is equally important.

Now you have a string ss with length nn and a string tt with length mm. Find out the longest subsequence in the string ss so that the lexicographical order of this subsequence is strictly larger than tt.

Input

two integers nn, mm in the first line 

(All characters are lowercase letters)

The second line is a string ss

The third line is a string tt

  • 1 \le n,m \le 10^61≤n,m≤106

Output

Output an integer representing the longest length, otherwise output -1.

樣例輸入1複製

9 3
aaabbbccc
abc

樣例輸出1複製

6

樣例輸入2複製

9 3
aaabbbccc
zzz

樣例輸出2複製

-1

題意:

給你n,m(1<=n,m<=1e6),再給你長度分別爲n,m的兩個字符串s和t,求s中字典序嚴格大於t的子序列的最長長度。如果不存在輸出-1。

思路:

作爲本場我第一個看的題,最後也沒過。賽後發現一個細節寫錯了,菜的真實。

看似字符串題,實際上只需要貪心一下。因爲是子序列,我們先找到s中第一個大於t[0]的字符的位置,s從這個位置剩下的串即爲初始化的答案。如果s串中所有字符嚴格小於t串的字符,那就是-1。然後開始維護兩個指針i,j,和一個相同前綴長度num,拿s[i]和t[j]比較,如果s[i]<t[j]則忽略(即i++),若s[i]>t[j]則可以 break了(參考初始化的情況),否則找到s[i]後面第一個大於t[j]的字符的位置,設爲pos,用num+n-pos更新答案。

然後num++,j++,i++,繼續重複上述步驟,直到結束,判斷一下i==n和j==m的情況。

對於pos的查找,我先用一個vector[i]存s串中嚴格大於字符i的所有字符的下標,然後二分查找即可。

(未必是最優的解法,但是可以過,歡迎提供更簡潔易懂,複雜度更優的解法)

代碼:

#pragma comment(linker,"/STACK:10240000,10240000") //防爆棧
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=1000010;
char s[maxn],p[maxn];
int n,m,len,nxt[maxn];
int cnt,ans;
vector<int>vc[26];
vector<int>::iterator it,itt;
int main()
{
    int t,i,cas=1;//這個i坑死我了
    scanf("%d%d",&n,&m);
    scanf("%s",p);
    scanf("%s",s);
    int pos=0,ans=0,fg=0;cnt=0;
    for(;pos<n;pos++)
    {
        int nn=p[pos]-'a'-1;
        rep(j,0,nn) vc[j].push_back(pos);//比賽的時候這裏寫成i,WA,編譯沒報錯,論不要亂定義變量的重要性
        if(p[pos]>=s[0]) fg=1;
        if(p[pos]>s[0])
        {
            ans=max(ans,n-pos);
        }
    }
    if(!fg) puts("-1");
    else
    {
        fg=0;
        int j=0,num=0;
        rep(i,0,n-1)
        {
            if(p[i]<s[j]) continue;
            else if(p[i]>s[j])
            {
                num+=(n-i);
                fg=1;
                break;
            }
            else
            {
                int nn=s[j]-'a';
                it=lower_bound(vc[nn].begin(),vc[nn].end(),i);
                if(it!=vc[nn].end())
                ans=max(ans,num+n-(*it));
                j++;
                num++;
                if(num+n-i-1<=ans) {fg=1;break;}
                if(j==m)
                {
                    if(i<n-1)
                    {
                        num+=(n-i-1);
                        fg=1;
                        break;
                    }
                    break;
                }
            }
        }
        if(fg) ans=max(ans,num);
        if(ans==0) puts("-1");
        else printf("%d\n",ans);
    }
    return 0;
}

 

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