cf1701 E. Text Editor
题意:
初始有字符串 \(s\),光标在 \(s\) 的末尾(即最后一个字符后面)。你可以按键盘上的 "left","right","home","end","backspace" 键,问把 \(s\) 变成 \(t\) 最少需要几次按键
\(1\le |t|\le |s|\le 5000\)
思路:
根据常识,最优方案就是要么只按 "left" 和 "backspace" 两个键;要么先按若干次 "left" 和 "backspace",再按一下 "home",再按若干 "right" 和 "backspace"
枚举 \(is,it\),表示 \(t[it+1,nt]\) 已经被 \(s[is+1,ns]\) 匹配好了。\(f(is,it)\) 表示 \(s\) 中以 \(is\) 位置结尾,\(t\) 中以 \(it\) 位置结尾,在两串中均连续且相等的最长子串的长度。那么我们现在按下 "home" 键,把开头那段处理一下就行了
注意 \(s\) 中要留够字符来匹配 \(t\) 的开头和结尾两段
const signed N = 5 + 5000;
int ns, nt; char s[N], t[N];
int f[N][N], l[N], r[N];
int sol() {
cin >> ns >> nt >> s + 1 >> t + 1;
for(int it = 1, is = 1; it <= nt; it++, is++) {
while(s[is] != t[it] && is <= ns) is++;
if(is > ns) return -1;
l[it] = is;
}
for(int it = nt, is = ns; it >= 1; it--, is--) {
while(s[is] != t[it]) is--;
r[it] = is;
}
r[nt+1] = INF;
int ans = ns; //不进行home操作
for(int it = 1; it <= nt; it++)
for(int is = 1; is <= ns; is++) {
f[is][it] = 0; //init
if(s[is] == t[it]) {
f[is][it] = f[is-1][it-1] + 1; //更新f
if(l[it-f[is][it]] <= is-f[is][it] && r[it+1] >= is+1) //满足条件
ans = min(ans, ns-f[is][it]+is-it+(is>it)); //更新答案
}
}
return ans;
}

浙公网安备 33010602011771号