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;
}

浙公网安备 33010602011771号