BJ模拟:string(后缀数组+Trie+ST表+分块)
来源:互联网 发布:java bigdecimal 长度 编辑:程序博客网 时间:2024/05/17 23:23
给定一个长度为
m 的01串A ,n 个长度为Li 的01串Bi (总长为L )。另有一个长度为n 的序列ci ,表示Bi 被选中1次的代价。要求将A划分成若干个串,并为每个划分出来的子串找一个Bki (ki 可以重复,重复代价算多次),满足此子串是Bki 的前缀或后缀。求最小总代价,如果不存在这样的划分,输出−1 。
为了造福群众,把数据放出来吧:https://pan.baidu.com/s/1mi68ZMS
题解:
基本上A了这道题字符串的板都差不多了。。
首先很容易想到
那么朴素的转移是
考虑将字符串分组,小于
可以考虑先
对于那些大于
算了讲得太辣鸡了还是把题解贴下来吧:
#include<bits/stdc++.h>typedef long long ll;using namespace std;inline int rd(){ char ch=getchar();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();} return i*f; }const int N=1e6+50+2e5,S=600;const ll INF=0x3f3f3f3f3f3f3f3f;int n,m,L,R,len[N],c[N],prep[N],sufp[N],Log[N*2],num[N],tot;char a[N],b[N];struct SuffixArray{ int rc,ch[N],len,tp1[N*2],tp2[N*2],*rk,*sa2,sa[N*2],ht[N][21]; SuffixArray(){rk=tp1;sa2=tp2;rc=2;} inline int ins(char *str){ int l=strlen(str+1);int tp=len+1; for(int i=1;i<=l;i++)ch[++len]=str[i]-'0'; ch[++len]=++rc; return tp; } inline void Rsort(){ static int cnt[N]; for(int i=1;i<=rc;i++)cnt[i]=0; for(int i=1;i<=len;i++)cnt[rk[i]]++; for(int i=1;i<=rc;i++)cnt[i]+=cnt[i-1]; for(int i=len;i>=1;i--) sa[cnt[rk[sa2[i]]]--]=sa2[i]; } inline void init(){ for(int i=1;i<=len;i++)rk[i]=ch[i],tp2[i]=i; Rsort(); for(int p=0,w=1;rc!=len;p=0,w<<=1){ for(int i=len-w+1;i<=len;i++)sa2[++p]=i; for(int i=1;i<=len;i++)if(sa[i]>w)sa2[++p]=sa[i]-w; Rsort();swap(rk,sa2);rk[sa[1]]=(p=1); for(int i=2;i<=len;i++){ int p1=sa[i],p2=sa[i-1]; rk[sa[i]]=(sa2[p1]!=sa2[p2]||sa2[p1+w]!=sa2[p2+w])?(++p):p; } rc=p; } for(int i=1,k=0;i<=len;i++){ k?k--:0;if(rk[i]==1)continue; int p1=sa[rk[i]-1]; while(ch[p1+k]==ch[i+k]) ++k; ht[rk[i]][0]=k; } for(int i=1;i<=20;i++){ for(int j=1;j<=len&&(j+(1<<i)-1)<=len;j++){ ht[j][i]=min(ht[j][i-1],ht[j+(1<<(i-1))][i-1]); } } } inline int getpre(int l,int r){ l=rk[l]; r=rk[r]; if(l>r)swap(l,r); ++l; int t=Log[r-l+1]; return min(ht[l][t],ht[r-(1<<t)+1][t]); }}sa;struct Trie{ int mn[N],son[N][2],cnt; Trie(){ memset(mn,0x3f,sizeof(mn)); cnt=1; } inline void ins(char *str,int v){ int pos=1,l=strlen(str+1); for(int i=1;i<=l;i++){ int t=str[i]-'0'; if(!son[pos][t])son[pos][t]=++cnt; pos=son[pos][t];mn[pos]=min(mn[pos],v); } }}trie_pre,trie_suf;struct Block{ ll mn[S+50],v[S+50][S+50]; Block(){ memset(mn,0x3f,sizeof(mn)); memset(v,0x3f,sizeof(v)); } inline void upt(int pos,ll val){ int p=(pos-1)/S+1; mn[p]=min(mn[p],val); v[p][(pos-1)%S+1]=min(v[p][(pos-1)%S+1],val); } inline ll querymn(int pos){ int t=(pos-1)/S+1; ll rs=INF; for(int i=pos;i<=m&&(i%S!=1);++i){ rs=min(rs,v[t][(i-1)%S+1]); } if(pos%S!=1)++t; while(t<=R)rs=min(rs,mn[t++]); return rs; }}bl; struct SparseTable{ ll dp[N][21]; SparseTable(){ memset(dp,0x3f,sizeof(dp)); } inline ll getmn(int l,int r){ int t=Log[r-l+1]; return min(dp[l][t],dp[r-(1<<t)+1][t]); } inline void upt(int p){ int pos=1;ll rs=INF; for(int i=p;i>=1&&i>i-S;i--){ int t=a[i]-'0'; if(!trie_suf.son[pos][t])break; pos=trie_suf.son[pos][t]; rs=min(rs,dp[i-1][0]+trie_suf.mn[pos]); } for(int i=1;i<=tot;i++){ int l=sa.getpre(2*m-p+2,sufp[i]); if(l>p) l=p; if(l) rs=min(rs,getmn(p-l,p-1)+c[i]); } dp[p][0]=min(rs,bl.querymn(p)); for(int i=1;i<=20;i++){ int t=p-(1<<i)+1; if(t<0)break; dp[t][i]=min(dp[t][i-1],dp[t+(1<<(i-1))][i-1]); } }}st;inline void update_pre(int p){ int pos=1; for(int i=p+1;i<=m&&i<=p+S;i++){ int t=a[i]-'0'; if(!trie_pre.son[pos][t])break; pos=trie_pre.son[pos][t]; bl.upt(i,st.dp[p][0]+trie_pre.mn[pos]); } for(int i=1;i<=tot;i++){ int l=sa.getpre(p+1,prep[num[i]]); if(l>m-p) l=m-p; if(l) bl.upt(p+l,st.dp[p][0]+c[num[i]]); }}int main(){ scanf("%d%d%d",&m,&n,&L); Log[1]=0; R=(m-1)/S+1; scanf("%s",a+1); sa.ins(a); reverse(a+1,a+m+1); sa.ins(a); reverse(a+1,a+m+1); for(int i=1;i<=n;i++){ scanf("%d%s",&c[i],b+1); int len=strlen(b+1); if(len<=S)trie_pre.ins(b,c[i]);else num[++tot]=i, prep[i]=sa.ins(b); reverse(b+1,b+len+1); if(len<=S)trie_suf.ins(b,c[i]);else sufp[i]=sa.ins(b); } sa.init(); for(int i=2;i<=sa.len;i++) Log[i]=Log[i>>1]+1; st.dp[0][0]=0; update_pre(0); for(int i=1;i<=m;i++){ st.upt(i); update_pre(i); } cout<<(st.dp[m][0]>=INF?-1:st.dp[m][0])<<endl;}
阅读全文
0 0
- BJ模拟:string(后缀数组+Trie+ST表+分块)
- BJ模拟 Mr. Panda and Fantastic Beats(广义后缀自动机、trie树上后缀自动机)
- BJ模拟 等差数列(分块+FFT)
- [BZOJ3277]串(后缀数组+二分+st表)
- [BZOJ3230]相似子串(后缀数组+二分+st表)
- bzoj3230: 相似子串(后缀数组+ST表)
- [BZOJ2534]Uva10829L-gap字符串(后缀数组+st表)
- bzoj 2534: Uva10829L-gap字符串 (后缀数组+ST表)
- bzoj 4310: 跳蚤 (后缀数组+二分+ST表)
- HDU 4622 Reincarnation(后缀数组+ST)
- [SPOJ687]REPEATS - Repeats(后缀数组+st)
- [BZOJ4698][Sdoi2008]Sandy的卡片(后缀数组+st表||后缀自动机)
- [BZOJ2741][FOTILE模拟赛]L(trie+分块)
- [BZOJ2741][FOTILE模拟]L(分块+可持久化Trie)
- BZOJ2741: 【FOTILE模拟赛】L(分块+可持续化Trie)
- BJ模拟:stwell(BFS)
- hdu4691(后缀数组+ST算法)
- hdu4622(后缀数组+ST算法)
- Python.CVXPY学习指南二
- Android SDK目录说明
- Linux系统使用-挂载NTFS格式硬盘
- Python学习迭代器与生成器
- 递归函数及memset函数
- BJ模拟:string(后缀数组+Trie+ST表+分块)
- 基于ZigBee的物联网家居系统学习-android端app的问题The type java.lang.Class cannot be resolved. It is indirectly refer
- numpy学习
- Spring实战-读书笔记-01
- k-近邻算法实现手写数字识别系统
- 深度学习,写在前面
- 抖音带给我们的意义是什么?
- leetcode 653. Two Sum IV
- Mybatis3源码分析(21)-Mapper实现-动态代理