【旅行】题解
题目大意,求出最长公共子序列(拉出序列(多个))。
分析:先用 dp 求出长度
l
e
n
len
len。接下来用搜索拉出序列。
注意:若两个串相同,则它们尾部相等(显然)。
所以定义
r
a
[
i
]
[
j
]
ra[i][j]
ra[i][j] 为在 s1 中,前
i
i
i 个字符中字符为
j
+
′
0
′
j+'0'
j+′0′ 的最大下标。
r
b
[
i
]
[
j
]
rb[i][j]
rb[i][j] 同理。
那么有:
for(int i = 1;i <= n1; i++) // 下标
for(int j = 0;j < 26; j++) // 'a'~'z'
if(c1[i] == char('a' + j)) ra[i][j] = i;
else ra[i][j] = ra[i - 1][j];
我们要找子串,因为其字符分别相同,所以
j
j
j 相等,分别寻找
i
i
i 即可。
在搜索的角度思考:传入参数
x
x
x,
y
y
y,
l
e
n
len
len,
c
c
c。分别表示 s1的前
x
x
x 个字符,s2的前
y
y
y 个,子串还剩的长度,目前的子串。
枚举字符 k k k,找到其在两字符串中的最后位置 t 1 t1 t1 和 t 2 t2 t2,当 s 1 [ 1... t 1 ] s1[1...t1] s1[1...t1] 和 s 2 [ 1... t 2 ] s2[1...t2] s2[1...t2] 中有长度为 l e n len len 的相同子串时,就往前搜索。
若
l
e
n
len
len 为
0
0
0,说明已经查找到一个解,存入 string 数组,输出时排序即可。
void dfs(int x, int y, int len, string c) {
if(!len) {
s[++sum] = c;
return ;
}
for(int k = 0;k < 26; ++k) {
int t1 = ra[x][k], t2 = rb[y][k];
if(dp[t1][t2] == len) {
dfs(t1 - 1, t2 - 1, len - 1, char(k + 'a') + c); // 当前字符在存入子串
}
}
}

浙公网安备 33010602011771号