辽宁省CSP-J 复赛能力测评解题报告
F 嗲串
一个词连着说两遍就会变得很嗲,比如“花花”、“狗狗”、“肚肚”,一个字符串如果它的长度为偶数且前一半和后一半完全一样,那么这个串被称为嗲串。
现在给你一个字符串,请你回答:最少需要删掉几个字符,使得剩下的字符串是一个嗲串。
数据范围:$ 1 \le s.length \le 50 $
输入描述
输入仅一行,一个字符串
。
输出描述
输出仅一行,表示最少删掉的字符数
样例的输入与输出
输入样例
singing
输出样例
1
做法 1:BFS 暴力搜索(88 分)
像走迷宫,枚举原字符串删除 1 个字符的所有情况,check 一下是不是嗲串,如果是那么答案就是 1;
如果没找到,在上一步的基础上再删除 1 个字符,这样就枚举了原字符串删除 2 个字符的所有情况,check 一下是不是嗲串,如果是那么答案就是 2;
以此类推……
这里需要注意,对每个字符串都需要打个 vis 标记表示访问过了,因为我们不希望重复搜索相同的字符串。
代码如下:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#define endl '\n'
#define LL long long
using namespace std;
map<string, int> vis;
struct Node {
string s;
int step;
};
queue<Node> que;
bool check(string str) {
int len = str.length();
if(len % 2 == 1) return 0;
for(int i=0; i<len/2; ++i) {
if(str[i] != str[len/2+i]) return 0;
}
return 1;
}
void Sol() {
string str;
cin >> str;
que.push((Node){str, 0});
vis[str] = 1;
while(!que.empty()) {
Node cur = que.front(); que.pop();
string s = cur.s; int len = s.length();
if(check(s)) {
cout << cur.step;
break;
}
for(int i=0; i<len; ++i) {
string temp = s;
temp.erase(i, 1);
// cout << temp << endl;
if(vis[temp] == 0) {
vis[temp] = 1;
que.push((Node){temp, cur.step+1});
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
Sol();
return 0;
}
做法 2:最长公共子序列 DP(100 分)
从原字符串删除若干个字符,那么修改后的字符串就是原来字符串的一个子序列。
我们可以把原字符串拆成两半,求解这两半的LCS,枚举一下得出答案。
代码如下:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <cstring>
#define endl '\n'
#define LL long long
using namespace std;
int f[101][101];
string str;
int check(string s1, string s2) {
memset(f, 0, sizeof(f));
int len1 = s1.length();
int len2 = s2.length();
for(int i=0;i<len1;++i)
{
for(int j=0;j<len2;++j)
{
if(s1[i]==s2[j]) f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
int maxPatternLen = f[len1-1][len2-1];
// cout << maxPatternLen << endl;
return str.length() - (maxPatternLen << 1);
}
void Sol() {
cin >> str;
int ans = 0x7fffffff;
int len = str.length();
for(int mid=0; mid<len-1; ++mid)
{
string s1 = str.substr(0, mid+1);
string s2 = str.substr(mid+1, (len-1) - (mid+1) + 1);
// cout << s1 << " " << s2 << endl;
ans = min(ans, check(s1, s2));
}
cout << ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
Sol();
return 0;
}
从0到1很难,但从1到100很容易

浙公网安备 33010602011771号