当前位置: 首页 > news >正文

一次遍历+维护前后缀+枚举中间+位运算

lc2484

前缀、后缀数组分别统计数字对的出现次数,枚举字符串中间字符

累加前后缀相同数字对的乘积,得到长度为5的回文子序列总数。

class Solution {
const long MOD = 1e9 + 7;
public:
int countPalindromes(string s) {
int suf[10]{}, suf2[10][10]{}, pre[10]{}, pre2[10][10]{};
for (int i = s.length() - 1; i >= 0; --i) {
char d = s[i] - '0';
for (int j = 0; j < 10; ++j)
suf2[d][j] += suf[j];
++suf[d]; //预处理后缀
}

long ans = 0L;
for (char d : s) {
d -= '0';
--suf[d];
for (int j = 0; j < 10; ++j)
suf2[d][j] -= suf[j]; // 撤销


for (int j = 0; j < 10; ++j)
for (int k = 0; k < 10; ++k)
ans += (long) pre2[j][k] * suf2[j][k]; // 枚举所有字符组合


for (int j = 0; j < 10; ++j)
pre2[d][j] += pre[j];
++pre[d];

}
return ans % MOD;
}
};

lc1930

unordered_map<char, pair<int, int>> hash;算起止

class Solution {
public:
int countPalindromicSubsequence(string s)
{
int n = s.size();
unordered_map<char, pair<int, int>> hash;
for (int i = 0; i < n; ++i)
{
if (!hash.count(s[i]))
hash[s[i]].first = i;
hash[s[i]].second = i;
}
int ret = 0;
for (auto& [ch, pos] : hash) {
int first = pos.first;
int last = pos.second;
if (last - first < 2) continue; // 中间没有字符,无法形成长度为3的回文
unordered_set<char> st;
for (int i = first + 1; i < last; ++i)
st.insert(s[i]);
ret += st.size();
}
return ret;
}
};

优化

一次遍历+维护前后缀+枚举中间+位运算

前缀后缀二进制标记字符存在性

枚举字符串中间字符作为回文中心

has[mid] |= pre & suf;

累加得到长度为3的回文子序列总数

for (int mask : has)
ans += popcount((uint32_t) mask);

算法就是 一次遍历 不断维护

class Solution {
public:
int countPalindromicSubsequence(string s) {
int n = s.size();
// 统计 [1,n-1] 每个字母的个数
int suf_cnt[26]{};
int suf = 0;
for (int i = 1; i < n; i++) {
int ch = s[i] - 'a';
suf_cnt[ch]++;
suf |= 1 << ch; // 把 ch 记录到二进制数 suf 中,表示后缀有 ch
}

int pre = 0;
int has[26]{}; // has[mid] = 由 alpha 组成的二进制数
for (int i = 1; i < n - 1; i++) { // 枚举中间字母 mid
int mid = s[i] - 'a';
suf_cnt[mid]--;

// 撤销 mid 的计数,suf_cnt 剩下的就是后缀 [i+1,n-1] 每个字母的个数
if (suf_cnt[mid] == 0)

// 后缀 [i+1,n-1] 不包含 mid
suf ^= 1 << mid;

// 从 suf 中去掉 mid

pre |= 1 << (s[i - 1] - 'a');

// 把 s[i-1] 记录到二进制数 pre 中,表示前缀有 s[i-1]
has[mid] |= pre & suf;

// 计算 pre 和 suf 的交集,|= 表示把交集中的字母加到 has[mid] 中
}

int ans = 0;
for (int mask : has) {
ans += popcount((uint32_t) mask);

//每个字符 has一个的记录表

// mask 中的每个 1 对应着一个 alpha
}
return ans;
}
};

http://www.jsqmd.com/news/224647/

相关文章:

  • Qwen2.5-7B远程办公:云端GPU让老家电脑变工作站
  • AI如何帮你掌握Vue2生命周期?自动生成代码示例
  • 零基础入门:5分钟用UPnP搭建家庭网络共享
  • 告别重复代码:Hutool让你的开发效率提升300%
  • 1小时打造中国区域经济数据原型系统
  • 达梦数据库连接效率提升全攻略
  • Qwen3-VL-WEBUI部署指南:Linux服务器环境准备步骤
  • 中文命名实体识别迁移部署:RaNER模型跨平台方案
  • 5个最火AI模型镜像推荐:Qwen2.5开箱即用,10元全体验
  • JAVA SPI入门指南:从零到实战
  • RaNER模型长文本处理:分段识别与结果合并策略
  • Qwen2.5-7B开箱测评:2块钱体验最新代码大模型
  • Qwen2.5-7B论文辅助神器:云端GPU快速部署,1小时1块钱
  • Qwen3-VL视觉编码教程:网页前端自动生成案例
  • HTOP实战:5个运维工程师必备的高级技巧
  • AI助力JProfiler:智能分析Java性能瓶颈
  • Qwen3-VL-WEBUI一文详解:从环境部署到网页推理完整流程
  • Qwen3-VL-WEBUI教育辅助实战:课件解析部署教程
  • 传统调试 vs AI修复:NumPy错误处理效率对比
  • PL/SQL开发效率提升:从3天到3小时的秘诀
  • Qwen2.5-7B跨区域部署:全球低延迟访问,月省30%成本
  • Qwen3-VL-WEBUI艺术创作辅助:动漫风格识别与生成教程
  • VENERA任务重现:用现代技术模拟金星着陆器
  • Qwen2.5-7B极简部署:3步搞定,小白也能当AI工程师
  • 5分钟用HEVC搭建视频转码原型系统
  • Qwen3-VL-WEBUI功能实测:名人与地标识别覆盖广度验证
  • Qwen3-VL-WEBUI自动扩缩容:流量波动应对部署实战
  • Qwen3-VL-WEBUI部署教程:文本-时间戳对齐功能配置详解
  • 6G ISAC突破性方案:PRS与PDSCH叠加,破解频谱效率与感知模糊双重瓶颈【附MATLAB代码】
  • Qwen3-VL部署案例:智能零售货架识别系统