贡献法解决子串问题

对于一个字符串 S,我们定义 S 的分值 f(S)S 中恰好出现一次的字符个数。

例如 f(aba)=1f(abc)=3, f(aaa)=0

现在给定一个字符串 S[0n1](长度为 n),请你计算对于所有 S 的非空子串 S[ij](0ij<n)f(S[ij]) 的和是多少。

贡献法:考虑当前这个字母可以在多少个子串中贡献,找到左边最近的相同字母,右边最近的相同字母,左右乘法原理计算可贡献子串数

  • 会爆longlong,并且只开ans不够

实现: 用哈希表正序逆序扫一遍,注意对于左右边界的处理时假设0和n+1存在相同字母

// Problem: 子串分值 // Contest: AcWing // URL: https://www.acwing.com/problem/content/2871/ // Memory Limit: 64 MB // Time Limit: 1000 ms int a[N]; int l[N],r[N]; map<char,int>mp; void solve(){ string s;cin>>s;ll ans=0; int len=s.size(); string tmp=" "; tmp+=s; for(int i=1;i<=len;i++){ if(mp[tmp[i]]){ l[i]=mp[tmp[i]]; mp[tmp[i]]=i; } else { l[i]=0; mp[tmp[i]]=i; } } mp.clear(); for(int i=len;i>=1;i--){ if(mp[tmp[i]]){ r[i]=mp[tmp[i]]; mp[tmp[i]]=i; } else { r[i]=len+1;; mp[tmp[i]]=i; } } for(int i=1;i<=len;i++){ ans+=(i-l[i])*(r[i]-i); } cout<<ans<<endl; }
posted @   potential-star  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示