官方题解 | 散落の字符
2025-04-12 18:34:47
发布于:云南
70阅读
0回复
0点赞
T6 散落の字符:Manacher算法、大模拟
题意说明
本次题目比较复杂,需要我们计算以下问题的答案。
- 通过迷宫的最小花费 。
- 转换  并拼接到  后面,转换  为 01字符串。
- 计算转换为偶回文串最小花费 的值。
- 连接 和 ,计算最长回文串 的值。
走迷宫
这一部分采用任何搜索算法均可。期待大家给出出题组没做出来的 dp 的办法。以下是 dijkstra 的做法:
struct Node {
    int x, y, cost;
    bool operator<(const Node& other) const {
        return cost > other.cost; // 最小堆
    }
};
void dijkstra() {
    priority_queue<Node> pq;
    pq.push({1, 1, migong[1][1]});
    vis[1][1] = true;
    while (!pq.empty()) {
        Node current = pq.top();
        pq.pop();
        int x = current.x, y = current.y, cost = current.cost;
        if (x == n && y == m) {
            ret = cost;
            return;
        }
        for (int i = 0; i < 4; ++i) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny]) {
                continue;
            }
            vis[nx][ny] = true;
            pq.push({nx, ny, cost + migong[nx][ny]});
        }
    }
}
转换与拼接
这一部分直接采用模拟即可。一个字符的ASCII码值为偶数是 的结果为 ,否则为 。
a=to_string(ret);
cin>>b;
d+=b;
for (int i = 0;i < a.size();++i){
	if (a[i]=='0'){
		d+=d[d.size()-1];
	}else{
		d+=monib[a[i]-'0'];
	}
}
for (int i = 0;i < d.size();++i){
	d[i]=((int)d[i])%2+'0';
}
t=d;
cin>>c;
c+=d;
计算 f 的值
在这一步中,我们需要推理一下。数据保证 可以转化为偶回文串,说明 的结果是偶数或者拼接后的 的中间值为 。如果是第二种可能,就只需要保证其它部分是偶回文串即可。
因此无论如何,只要保证拼接后的  是一个回文串即可保证是偶回文串。我们只需要从  一直到  遍历一遍,找到改变成偶回文串的最小花费。对于每个第  项,我们只需考虑是改变成 0 还是 1 的花费更小。
for(int i = 0;i < d.size() / 2;i++){
  if(d[i] == d[d.size() - i - 1]) continue;
  else ans1 += min(w[i],w[d.size() - i - 1]);
}
计算 l 的值
暴力做法:枚举每一段 l 中的子串。代码如下:
for(int i = 0;i < l.size();i++){
    for(int j = i + 1;j < l.size();j++){
        if(hw(l.substr(i,j + 1))) maxx = max(maxx,j - i + 1);
    }
}
时间复杂度:
预计得分:
我们可以使用 Manacher 算法来解决 的计算。回文自动机的 Manacher 算法可以在 时间中解决最长回文子串问题。
下面就是模板的 Manacher 算法了(这里使用 % 避免边界问题,若有想要深入学习的请见:这里):
int alen=c.size(),len=2;
s[0]='%';
s[1]='#';
for (int i=0;i<alen;++i){
    s[len++]=c[i];
    s[len++]='#';
}
s[len]='#';
int mid=1,r=1,ans1=-1;
for (int i=1;i<=len;++i){
    maxs[i]=0;
}
for (int i=1;i<=len;++i){
    if (i<r){
        maxs[i]=min(r-i,maxs[mid*2-i]);
    }else{
        maxs[i]=1;
    }
    while (s[i-maxs[i]]==s[i+maxs[i]]){
        maxs[i]+=1;
    }
    if (r<i+maxs[i]){
        mid=i;
        r=i+maxs[i];
    }
    ans1=max(maxs[i]-1,ans1);
}
时间复杂度:
预计得分:
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int hmod = 1e9 + 7, base = 31;
int n, m, migong[333][333], dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
long long w[200025], dp[200010], ret = 1e13;
bool vis[333][333];
char monib[30] = {'0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
string a, b, c, d, t;
char s[13000000];
int maxs[13000000];
struct Node {
    int x, y, cost;
    bool operator<(const Node& other) const {
        return cost > other.cost; // 最小堆
    }
};
void dijkstra() {
    priority_queue<Node> pq;
    pq.push({1, 1, migong[1][1]});
    vis[1][1] = true;
    while (!pq.empty()) {
        Node current = pq.top();
        pq.pop();
        int x = current.x, y = current.y, cost = current.cost;
        if (x == n && y == m) {
            ret = cost;
            return;
        }
        for (int i = 0; i < 4; ++i) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny]) {
                continue;
            }
            vis[nx][ny] = true;
            pq.push({nx, ny, cost + migong[nx][ny]});
        }
    }
}
signed main() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            cin >> migong[i][j];
        }
    }
    dijkstra();
    a = to_string(ret);
    cin >> b;
    d += b;
    for (int i = 0; i < a.size(); ++i) {
        if (a[i] == '0') {
            d += d[d.size() - 1];
        } else {
            d += monib[a[i] - '0'];
        }
    }
    for (int i = 0; i < d.size(); ++i) {
        d[i] = ((int)d[i]) % 2 + '0';
    }
    t = d;
    cin >> c;
    c += d;
    int alen = c.size(), len = 2;
    s[0] = '%';
    s[1] = '#';
    for (int i = 0; i < alen; ++i) {
        s[len++] = c[i];
        s[len++] = '#';
    }
    s[len] = '#';
    int mid = 1, r = 1, ans1 = -1;
    for (int i = 1; i <= len; ++i) {
        maxs[i] = 0;
    }
    for (int i = 1; i <= len; ++i) {
        if (i < r) {
            maxs[i] = min(r - i, maxs[mid * 2 - i]);
        } else {
            maxs[i] = 1;
        }
        while (s[i - maxs[i]] == s[i + maxs[i]]) {
            maxs[i] += 1;
        }
        if (r < i + maxs[i]) {
            mid = i;
            r = i + maxs[i];
        }
        ans1 = max(maxs[i] - 1, ans1);
    }
    for (int i = 0; i < t.size(); ++i) {
        cin >> w[i];
    }
    n = t.size();
    for (int i = 0; i < d.size() / 2; ++i) {
        if (d[i] == d[d.size() - i - 1]) continue;
        else ans1 += min(w[i], w[d.size() - i - 1]);
    }
    cout << ans1 << "\n";
    return 0;
}
时间复杂度:
预计得分:
全部评论 2
- 赛时切了 - 2025-04-12 来自 浙江 0- %%% - 2025-04-13 来自 北京 0
 
- %%%%% - 2025-04-12 来自 浙江 0









有帮助,赞一个