cdqz2017-test10-加帕里图书馆(区间DP & 简单容斥)
给定一个由小写字母组成的字符串,输出有多少重复的回文子序列
#include<cstdio> #include<cstring> using namespace std; #define N 2002 const int mod=1e9+7; int n; char s[N]; int f[N][N],g[N][N]; int pre[N][26],nxt[N][26]; int get_f(int l,int r) { if(l>r) return 1; int &ans=f[l][r]; if(ans!=-1) return ans; if(s[l]==s[r]) ans=get_f(l+1,r)+get_f(l,r-1); else ans=get_f(l+1,r)+get_f(l,r-1)-get_f(l+1,r-1); ans%=mod; if(ans<0) ans+=mod; return ans; } int get_g(int l,int r) { if(l==r) return 2; if(l>r) return 1; int &ans=g[l][r]; if(ans!=-1) return ans; if(s[l]!=s[r]) ans=get_g(l+1,r)+get_g(l,r-1)-get_g(l+1,r-1); else { if(nxt[l][s[l]-'a']>=r && pre[r][s[r]-'a']<=l) ans=get_g(l+1,r-1)*2+1; else if(nxt[l][s[l]-'a']==pre[r][s[r]-'a']) ans=get_g(l+1,r-1)*2; else ans=get_g(l+1,r-1)*2-get_g(nxt[l][s[l]-'a']+1,pre[r][s[r]-'a']-1); } ans%=mod; if(ans<0) ans+=mod; return ans; } void cal() { for(int i=1;i<=n;++i) { for(int j=i+1;j<=n;++j) if(!nxt[i][s[j]-'a']) nxt[i][s[j]-'a']=j; for(int j=i-1;j;--j) if(!pre[i][s[j]-'a']) pre[i][s[j]-'a']=j; } } int main() { freopen("library.in","r",stdin); freopen("library.out","w",stdout); scanf("%s",s+1); n=strlen(s+1); memset(f,-1,sizeof(f)); int all=get_f(1,n); cal(); memset(g,-1,sizeof(g)); int dif=get_g(1,n); int ans=all-dif; if(ans<0) ans+=mod; printf("%d",ans); }
爆搜代码
#include<cstdio> #include<cstring> using namespace std; int n; char s[2002]; char tt[2002],t[2002]; int L; int ans,sum; int cnt[27]; void find(int now,int len,int ok) { if(ok==len) { sum++; return; } for(int i=now+1;i<=n;++i) if(t[ok+1]==s[i]) find(i,len,ok+1); } void dfs(int len) { for(int i=0;i<26;++i) { tt[len]=char(i+'a'); L=0; for(int j=len;j;--j) t[++L]=tt[j]; for(int j=2;j<=len;++j) t[++L]=tt[j]; sum=0; find(0,L,0); if(sum>1) ans+=sum-1; if(sum) dfs(len+1); } } void dfs2(int len) { for(int i=0;i<26;++i) { tt[len]=char(i+'a'); L=0; for(int j=len;j;--j) t[++L]=tt[j]; for(int j=1;j<=len;++j) t[++L]=tt[j]; sum=0; find(0,L,0); if(sum>1) ans+=sum-1; if(sum) dfs2(len+1); } } int main() { freopen("library.in","r",stdin); freopen("library.out","w",stdout); scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;++i) cnt[s[i]-'a']++; dfs(1); dfs2(1); printf("%d",ans); }
分类:
数学——容斥原理
, 动态规划——区间DP
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· 程序员常用高效实用工具推荐,办公效率提升利器!
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 【译】WinForms:分析一下(我用 Visual Basic 写的)