scut 125. 笔芯回文

https://scut.online/p/125

看数据量,这题可能是O(n^2)的dp

也可能是区间dp,但是区间dp一般复杂度是O(n^3),虽然也可以优化,但是比赛的时候那么多人“秒”了,应该不会是那么麻烦的。

套路:设dp[i]表示前i个字符中能拿到的最大贡献。dp[len]就是答案。

如果[L, R]这段区间能组成回文串,那么就有两种决策,删除或则不删除。

删除:dp[R] = dp[L - 1] + a[R - L + 1]

不:  dp[R] = dp[R];

取个max就行。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + 20;
int a[maxn];
LL dp[maxn];
char str[maxn], sub[maxn];
int p[maxn];
int manacher(char str[], int lenstr) {
    str[0] = ‘*‘; //表示一个不可能的值
    //目标要插入lenstr+1个‘#‘,所以长度变成2*lenstr+1
    for (int i = lenstr; i >= 0; i--) { //str[lenstr+1]是‘\0‘
        //i=lenstr时,i+i+2那个值要赋为‘\0‘;
        //总长度只能是lenstr+lenstr+2,所以i从lenstr开始枚举
        str[i + i + 2] = str[i + 1];
        str[i + i + 1] = ‘#‘;
    }
    int id = 0, maxlen = 0; //现在开始在str[2]了
    for (int i = 2; i <= 2 * lenstr + 1; i++) { //2*lenstr+1是‘#‘没用
        if (p[id] + id > i) { //没取等号的,只能去到p[id]+id-1
            //p[id]+id是越界的,减去i即为区间长度
            //p[id]+id-i,这个是所有可能中的最大值了
            p[i] = min(p[id] + id - i, p[2 * id - i]);
        } else p[i] = 1; //记得修改的是p[i]
        while (str[i + p[i]] == str[i - p[i]]) ++p[i];
        if (p[id] + id < p[i] + i) id = i;
        maxlen = max(maxlen, p[i]);
    }
    return maxlen - 1;
}
bool isok(int be, int en) {
    int len = en - be + 1;
    be <<= 1;
    en <<= 1;
    int mid = (be + en) >> 1;
    return p[mid] - 1 >= len;
}
void work() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    memset(dp, 0, sizeof dp);
    cin >> str + 1;
    int lenstr = strlen(str + 1);
    strcpy(sub + 1, str + 1);
    manacher(str, lenstr);
    for (int i = 1; i <= lenstr; ++i) {
        for (int j = 1; j <= i; ++j) {
            if (i - j + 1 > n) continue;
            if (isok(j, i)) {
                dp[i] = max(dp[i], dp[j - 1] + a[i - j + 1]);
            }
        }
    }
    cout << dp[lenstr] << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    cin >> t;
    while (t--) work();
    return 0;
}

时间: 2024-07-28 13:47:24

scut 125. 笔芯回文的相关文章

SCUT 125 :笔芯回文(DP)

https://scut.online/p/125 125. 笔芯回文 题目描述 bxbx有一个长度一个字符串SS,bxbx可以对其进行若干次操作. 每次操作可以删掉一个长度为k(1 \leq k \leq n)k(1≤k≤n)的连续回文子串,bxbx获得a_ka?k??的愉悦值. 一个字符串是回文串当且仅当正读和反读都是一样的.例如"a", "aa", "abcba""a","aa","abcb

125验证回文串

Algorithm [leetcode]125验证回文串 https://leetcode.com/problems/valid-palindrome/ 1)problem 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: fal

前端与算法 leetcode 125. 验证回文串

目录 # 前端与算法 leetcode 125. 验证回文串 题目描述 概要 提示 解析 解法一:api侠 解法二:双指针 算法 传入测试用例的运行结果 执行结果 GitHub仓库 查看更多 # 前端与算法 leetcode 125. 验证回文串 题目描述 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: tru

125. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false 思路:从头尾开始同时遍历比较 目前 beat 95% class Solution { public boolean isPalindrome(String s) {

力扣(LeetCode)125. 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false java知识点 Java 字符串拼接,推荐使用StringBuilder String 本身没有反转函数 ,但是StringBuilder有 reverse() Str

[LeetCode] 125. 验证回文串

题目链接 : https://leetcode-cn.com/problems/valid-palindrome/ 题目描述: 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例: 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false 思路: 思路一: 用正则提取字母

leetcode.字符串.125验证回文串-Java

1. 具体题目 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写.说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, a plan, a canal: Panama" 输出: true 示例 2: 输入: "race a car" 输出: false 2. 思路分析 对于给定的字符串,其中可能包括有无效字符,所以需要先将原字符串中的无效字符去掉(用正则表达式判断),得到新字符串后用双指针比较首尾字符是否

Leetcode 125.验证回文串 By Python

思路 显然一个字符串不止包括字母和数字字符,所以我们可以先提取出来我们要进行比较的字符 还有一个问题是,字母是分大小写的,我们要统一大写或者统一小写,就是规范化 代码 class Solution(object): def isPalindrome(self, s): """ :type s: str :rtype: bool """ letters = string.ascii_letters digits = string.digits s

代码题(16)— 回文(1)

1.9. 回文数 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false 解释: 从左向右读, 为 -121 . 从右向左读, 为 121- .因此它不是一个回文数. 示例 3: 输入: 10 输出: false 解释: 从右向左读, 为 01 .因此它不是一个回文数. class Solution { public: bool isPalindrome(int x)