[JZOJ 4486] [GDOI 2016 Day 1] 두 번째 문제 최장 공용 꼬치.

5089 단어 dpGDOI2016

Description


두 개의 문자열 S를 주고, T는 N 개의 구간을 주며, S 문자열의 이 구간 내의 문자는 구간의 위치를 마음대로 바꿀 수 있다.S, T가 도달할 수 있는 가장 긴 공통 문자열의 길이를 구합니다.

Analysis


두 바늘로 움직일 수 있습니다. 제가 친 것은 dp입니다.f[i][j]로 S열의 i번째 구간과 T열의 j번째 문자를 나타내는 LCS를 설정합니다.한 무더기의 물건을 미리 처리하고 옮기면 스스로 뇌보한다.

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
const int N=2010;
struct section
{
    int l,r;
}a[102010],b[N];
int k,m,n,num,ans,sum['z'+1][N],h['z'+1][N],g[N],f[N][N];
char s[N],t[N];
bool cmp(section a,section b){return a.l<b.l || a.l==b.l && a.r<b.r;}
void pre()
{
    int k0;
    scanf("%s
%s
%d"
,t+1,s+1,&k0); m=strlen(t+1),n=strlen(s+1); fo(i,1,k0) scanf("%d %d",&a[i].l,&a[i].r),a[i].l++,a[i].r++; fo(i,1,n) a[++k0].l=a[k0].r=i; sort(a+1,a+k0+1,cmp); int l=a[1].l,r=a[1].r; a[k0+1].l=2147483647; fo(i,2,k0+1) if(r>=a[i].l) r=max(r,a[i].r); else b[++num].l=l,b[num].r=r,g[num]=r-l+1,l=a[i].l,r=a[i].r; fo(i,1,m) { fo(j,'a','z') sum[j][i]=sum[j][i-1]; sum[t[i]][i]++; } fo(i,1,num) fo(j,b[i].l,b[i].r) h[s[j]][i]++; } void dp() { fd(i,num,1) fd(j,m,1) { bool p=0; fo(k,j,min(m,j+g[i]-1)) { if(sum[t[k]][k]-sum[t[k]][j-1]>h[t[k]][i]) { p=1; break; } else f[i][j]++; } if(!p) f[i][j]+=f[i+1][j+g[i]]; int len=0; fd(k,j-1,max(1,j-g[i-1])) if(sum[t[k]][j-1]-sum[t[k]][k-1]>h[t[k]][i-1]) break; else len++; ans=max(ans,f[i][j]+len); } } int main() { freopen("lcs.in","r",stdin); freopen("lcs.out","w",stdout); pre(); dp(); printf("%d",ans); fclose(stdin);fclose(stdout); return 0; }

좋은 웹페이지 즐겨찾기