CF176DHyper String题解
考虑dp状态
dp[pre][len]考虑到s的前缀为pre,其与t的最大公共子序列为len的最小前缀
考虑转移
dp[pre][len]=min(dp[pre-1][len],在dp[pre-1][len-1]右面最靠左的和s[pre]相同的位置)
为了o(1)转移考虑预处理两个数组
dp1[i][j][k]表示在b[i]字符串上的第j个位置右面最靠左的字符为k的位置
dp2[i][k]表示在t[i]右面含有字符k的最靠左的位置
然后就可以ac这道题了
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<vector> #include<set> #include<algorithm> #define er -'a'+1 #define inf 0x3f3f3f3f #define maxn 2010 using namespace std; namespace lin { string s; string t[maxn]; struct linlin { int lin[30]; }; struct jialin { int num,id; jialin(){} jialin(int _num,int _id){ num=_num,id=_id; } friend bool operator < (jialin xx,jialin yy) { return xx.num>yy.num; } }; set<jialin>st; set<jialin>::iterator it; vector<linlin> dp1[maxn]; int wjll[maxn][30]; int dp2[maxn][30]; int dp[maxn][maxn];//dp[pre][len]考虑到s的前缀为pre,其与t的最大公共子序列为len的最小前缀 int vist[40]; int vis[30]; int a[maxn],sum[maxn]; int query(int x,int op) { if(x==inf) return inf; it=st.lower_bound(jialin(x,20060913)); jialin tmp=*it; int tt=tmp.id; if(sum[tt]==x) tt--; int sw=x-sum[tt<0?0:tt]; if(sw>0) if(dp1[a[tt+1]][sw-1].lin[op]) { return sum[tt]+dp1[a[tt+1]][sw-1].lin[op]; } tt=dp2[tt+1][op]; if((int)(t[a[tt]][0] er)==op) return sum[tt-1]+1; if(dp1[a[tt]][0].lin[op]) { return sum[tt-1]+dp1[a[tt]][0].lin[op]; } return inf; } int love(int wjl) { int n,m; ios::sync_with_stdio(false); cin.tie(NULL); cin>>n; for(int i=1;i<=n;i++) { cin>>t[i]; int siz=t[i].size(); for(int j=0;j<siz;j++) wjll[i][t[i][j] er]=1; } cin>>m; st.insert(jialin(0,0)); for(int i=1;i<=m;i++) { cin>>a[i]; sum[i]=sum[i-1]+(int)t[a[i]].size(); st.insert(jialin(sum[i],i)); } for(int i=m;i>=0;i--) { for(int j=1;j<=26;j++) dp2[i][j]=vist[j]; for(int j=1;j<=26;j++) if(wjll[a[i]][j]) vist[j]=i; } for(int i=1;i<=n;i++) { int siz=t[i].size(); memset(vis,0,sizeof(vis)); for(int j=siz-1;j>=0;j--) { linlin tmp; for(int z=1;z<=26;z++) tmp.lin[z]=vis[z]; dp1[i].push_back(tmp); vis[t[i][j] er]=j+1; } reverse(dp1[i].begin(),dp1[i].end()); } cin>>s; int nn=s.size(); memset(dp,0x3f,sizeof(dp)); dp[0][0]=0; linlin tmp; memset(tmp.lin,0,sizeof(tmp.lin)); dp1[0].push_back(tmp); for(int i=1;i<=nn;i++) { for(int j=0;j<=nn;j++) { if(i==3&&j==3) i++,i--; dp[i][j]=dp[i-1][j]; if(j!=0) dp[i][j]=min(dp[i][j],query(dp[i-1][j-1],s[i-1] er)); } } for(int i=nn;i>=0;i--) { if(dp[nn][i]!=inf) { cout<<i; return wjl; } } return wjl; } } signed main() { return lin::love(0); }

浙公网安备 33010602011771号