cf335 B. Palindrome(LCS找回文串)

题意:

给定小写字母串,输出一个长度为100的回文子序列。若找不到,就输出最长回文子序列。

\(1\le n \le 5e4\)

思路:

小写字母一共就26个。若 \(n\ge 2600\),一定有某个字母的出现次数 \(\ge 100\),输出之。

否则,原串与反串做 LCS,回溯输出答案。若LCS长度大于100就只输出前50个和后50个。

附一个 LCS+回溯输出的模板:

int f[N][N], path[N][N];
void LCS()
{
    for(int i = 1; i <= n; i++)
        path[i][0] = 1, path[0][i] = -1;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            if(s1[i] == s2[j])
                f[i][j] = f[i-1][j-1] + 1,
                path[i][j] = 0;
            else if(f[i-1][j] >= f[i][j-1])
                f[i][j] = f[i-1][j],
                path[i][j] = 1;
            else
                f[i][j] = f[i][j-1],
                path[i][j] = -1;
        }
}

void out(int x, int y)
{
    if(!x && !y) return;
    if(path[x][y] == 0) out(x-1, y-1), putchar(s1[x]);
    else if(path[x][y] == 1) out(x-1, y);
    else out(x, y-1);
}

LCS();
out(n, n);

上面是倒序输出LCS(先递归再输出)。回文串的话就无所谓了。

string ans;
void get50(int x, int y)
{
    if(ans.size() >= 50) return;
    if(path[x][y] == 0) ans.pb(s1[x]), get50(x-1, y-1);
    else if(path[x][y] == 1) get50(x-1, y);
    else get50(x, y-1);
}

LCS();
if(f[n][n] < 100)
    out(n, n);
else
{
    get50(n, n);
    cout << ans;
    reverse(all(ans));
    cout << ans;
}
posted @ 2022-02-10 23:26  Bellala  阅读(35)  评论(0)    收藏  举报