The Preliminary Contest for ICPC Asia Xuzhou 2019 M. Longest subsequence(思维+序列自动机)

序列自动机跑s串
假设k为s和t相同的长度,初始时相同长度为0
取s串中大于t[i]的最左边的位置,用n-tmp+1+i-1更新答案,tmp是最左端的位置
然后去t[i]相等的位置,走到下一位,如果下一位的位置不存在或者在tmp的右边,跳出循环即可。
最后就是s串中找出了一个和t串相同的串,之后的长度只要不为0,也是可以用来更新答案的。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int INF=0x3f3f3f3f;

int up[30],nxt[maxn][27];
char s[maxn],t[maxn];
int n,m;

void getNext()
{
    memset(up,INF,sizeof(up));
    for (int i=n;i>=0;i--) {
        for (int j=0;j<=25;j++) {
            nxt[i][j]=up[j];
        }
        if (i!=0) {
            up[s[i]-'a']=i;
        }

    }
}

int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    scanf("%s",t+1);
    int ans=-1;
    getNext();

    int tmp=INF;
    int loc=0;
    for (int i=1;i<=m;i++) {
        tmp=INF;
        for (int j=t[i]-'a'+1;j<=25;j++) {
            tmp=min(nxt[loc][j],tmp);
        }
        if (tmp!=INF) {
            ans=max(ans,n-tmp+1+i-1);
        }
        if (nxt[loc][t[i]-'a']==INF||nxt[loc][t[i]-'a']>tmp) {
            break;
        }
        else {
            loc=nxt[loc][t[i]-'a'];
        }

        if (i==m && m+n-loc>m) {
            ans=max(ans,m+n-loc);
        }
    }
    printf("%d\n",ans);
    return 0;
}
/*
8 3
aabcdccc
abc
ans=7
*/
posted @ 2019-09-24 20:26  xyee  阅读(114)  评论(0编辑  收藏  举报