题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6357
将枚举【i,j】区间化为枚举值域,原问题转化为两串的最长公共子序列问题,其中构造串可以重复的匹配
#include<bits/stdc++.h>
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define maxn 100005
using namespace std;
char s[maxn];
int a[maxn];
int b[maxn];
int ans,ansl,ansr;
int teml,temr;
int n;
int dp[maxn][22],tl[maxn][22],tr[maxn][22];
int pin(int cnt)
{
For(i,1,n)
For(j,1,cnt)
{
if(i==1)
{
dp[i][j]=0;
tr[i][j]=0;
tl[i][j]=0;
}
else
{
dp[i][j]=dp[i-1][j];
tr[i][j]=tr[i-1][j];
tl[i][j]=tl[i-1][j];
}
if(a[i]==b[j])
{
dp[i][j]++;
if(teml==j&&tl[i][j]==0)
tl[i][j]=i;
if(temr==j)
tr[i][j]=i;
}
if(dp[i][j]<dp[i][j-1])
{
dp[i][j]=dp[i][j-1];
tl[i][j]=tl[i][j-1];
tr[i][j]=tr[i][j-1];
}
}
return dp[n][cnt];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%s",s);
ans =-1;
ansl=0;
ansr=0;
int L=9,R=0;
bool f=1;
For(i,0,n-1)
{
a[i+1]=s[i]-'0';
L=min(L,a[i+1]);
R=max(R,a[i+1]);
if(a[i+1]<a[i-1])f=false;
}
// for(int i=1;i<=n;i++)
// printf("%d ",a[i]);
// printf("\n");
// if(L==R||f)
// {
// printf("%d %d %d\n",n,1,1);
// continue;
// }
int temp=0;
for(int i=L;i<=R;i++)
b[++temp]=i;
int ans=pin(temp);
ansl=1;
ansr=1;
// printf("L=%d R=%d\n",L,R);
For(l,L,R)
For(r,l+1,R)
{
// printf("l=%d r=%d\n",l,r);
int cnt=0;
for(int i=L;i<=l;i++)
b[++cnt]=i;
teml=cnt+1;
for(int i=r;i>=l;i--)
b[++cnt]=i;
temr=cnt;
for(int i=r;i<=R;i++)
b[++cnt]=i;
// for(int i=1;i<=cnt;i++)
// printf("%d ",b[i]);
// printf("\n");
// printf("teml=%d temr=%d\n",teml,temr);
int temans=pin(cnt);
// printf("ans=%d %d %d\n",temans,tl[n][cnt],tr[n][cnt]);
if(ans<temans&&tl[n][cnt]&&tr[n][cnt])
{
ans=temans;
ansl=tl[n][cnt];
ansr=tr[n][cnt];
}
}
printf("%d %d %d\n",ans ,ansl,ansr);
}
return 0;
}