例题+题解
序列自动机
int nxt[N][50];//a[i...n]中字母j的最近位置
int dp[50][50];//b中前i个字母匹配了j个,dp[i][j]表示最后一个匹配的字母在a中的位置
char a[N],b[N];
void get_nxt() //序列自动机
{
int lena=strlen(a+1);
for(int i=0; i<26; i++)
nxt[lena][i]=lena+1;
nxt[lena][a[lena]-'a']=lena;
for(int i=lena-1; i>=1; i--)
{
for(int j=0; j<26; j++)
{
nxt[i][j]=nxt[i+1][j];
}
nxt[i][a[i]-'a']=i;
}
}
int l,r;
scanf("%d%d",&l,&r);
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[0][0]=l-1;
for(int i=1; i<=lenb; i++)
{
dp[i][0]=l-1;
for(int j=1; j<=i; j++)
{
if(dp[i-1][j]<=r)
dp[i][j]=min(dp[i][j],dp[i-1][j]);//b[j]不匹配
if(dp[i-1][j-1]<r)
dp[i][j]=min(dp[i][j],nxt[dp[i-1][j-1]+1][b[i]-'a']);//b[j]匹配
}
}
int tmp=lenb;
while(tmp)
{
if(dp[lenb][tmp]<=r)//如果匹配上了,那么tmp就是b在a的最长公共子序列
break;
tmp--;
}
printf("%d\n",r-l+1+lenb-tmp*2);//求从b转换成a最少的步数,就是求a+b-两倍他们公共最长子序列