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); }