辽宁省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;
}
posted @ 2024-08-15 16:05  qseer  阅读(49)  评论(0)    收藏  举报