题义
给出两个字符串a,b,求一个字符串,这个字符串是a和b的子串,且只在a,b中出现一次,要求输出这个字符串的最小长度。
解法
对于字符串a,求一个数组aa,aa[i]的值是,在所有以i为结尾的子串中,只会在a中出现一次的最小长度。对于b也求出数组bb[i]。
设dp[i][j]表示以a[i],b[j]为结尾的最长相同子串的长度
如果有一个dp[i][j]大于a[i]且大于b[j],就用max(a[i],b[j])更新答案
至于aa[i]怎么求,是先求出dp[i][j]表示以a[i],a[j]为结尾的最长相同子串的长度,那么aa[i]是max(dp[i][j])+1,其中0<=j<lena&&j!=i
#include<cstdio>
#include<cstring>
char a[5005],b[5005];
int dp[5005][5005],aa[5005],bb[5005];
int max(int a,int b)
{
return a>b?a:b;
}
void getdp(char *s1,int l1,char *s2,int l2)
{
int i,j;
for(i=0;i<l1;i++)
{
if(s1[i]==s2[0])
dp[i][0]=1;
else
dp[i][0]=0;
}
for(i=0;i<l2;i++)
{
if(s1[0]==s2[i])
dp[0][i]=1;
else
dp[0][i]=0;
}
for(i=1;i<l1;i++)
for(j=1;j<l2;j++)
{
if(s1[i]==s2[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=0;
}
}
int main()
{
int i,j;
gets(a);gets(b);
int lena=strlen(a),lenb=strlen(b);
getdp(a,lena,a,lena);
for(i=0;i<lena;i++)
{
int mx=-1;
for(j=0;j<lena;j++)
{
if(i==j)
continue;
if(dp[i][j]>mx)
mx=dp[i][j];
}
aa[i]=mx+1;
}
getdp(b,lenb,b,lenb);
for(i=0;i<lenb;i++)
{
int mx=-1;
for(j=0;j<lenb;j++)
{
if(i==j)
continue;
if(dp[i][j]>mx)
mx=dp[i][j];
}
if(mx==-1)
bb[i]=1;
else
bb[i]=mx+1;
}
getdp(a,lena,b,lenb);
int ans=-1;
for(i=0;i<lena;i++)
for(j=0;j<lenb;j++)
{
if(dp[i][j]<aa[i]||dp[i][j]<bb[j])
continue;
int res=max(aa[i],bb[j]);
if(ans==-1||res<ans)
ans=res;
}
printf("%d\n",ans);
return 0;
}