(清题笔记)hdu2020 round 2 String Distance

题目描述

对于两个字符串S和T,可以对任意次数执行以下操作:Select a string
S或T,在任何位置插入或删除字符。两个弦S和T之间的距离被定义了
作为使S和T相等的最小操作数。
您将得到两个字符串A[1…n]、B[1…m]和q查询。
在每个查询中,您将得到两个整数li和ri(1≤li≤ri≤n),您需要先查找距离
在连续的子串A[li…ri]和整个串B之间。

输入

输入的第一行包含单个整数T(1≤T≤10),即测试用例的数量。
对于每种情况,输入的第一行包含一个由n(1≤n≤100 000)小写组成的字符串a
英文字母。
输入的第二行包含一个字符串B,由m(1≤m≤20)个小写英文字母组成。
输入的第三行包含单个整数q(1≤q≤100000),表示查询的数量。
然后在下面的q行中,每行有两个整数li,ri(1≤li≤ri≤n),表示一个查询。

输出

对于每个查询,打印一行包含整数,表示答案
思路:求出两字符串的最长公共子串lcs;用r-l+1+m-2*lcs就可以求出操作数。
用dp[j]表示长度为j时,在i之前a串中最早结束的位置
用 nt[i][j]表示从i开始,首次出现字母j的位置 。找到最大公共子串长度。

代码

include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int inf=0x3f3f3f3f;

const int N=1e5+100;

char a[N],b[N];

int nt[N][26],dp[25];
int main(){
  int w;    
cin>>w;     
while(w--)    

{        

scanf("%s%s",a+1,b+1);       

int n=strlen(a+1),m=strlen(b+1);       

for(int i=0;i<26;i++)           

nt[n+1][i]=n+1;        

for(int i=n;i>=0;i--)        

{            

for(int j=0;j<26;j++)                     
nt[i][j]=nt[i+1][j];            

   
if(i>0)                

   
nt[i][a[i]-'a']=i;        

 
}        

   
int q;           
scanf("%d",&q);       


 
while(q--)        

{            

int l,r;           
   
scanf("%d%d",&l,&r);            

int lcs=0;            

memset(dp,inf,sizeof(dp));          

dp[0]=l-1;            
 
for(int i=1;i<=m;i++){

for(int j=m;j>=1;j--)               
   
{      

    
//dp[j]表示长度为j时,在i之前a串中最早结束的位置

    
// nt[i][j]表示从i开始,首次出现字母j的位置 

    
if(dp[j-1]<=r&&nt[dp[j-1]+1][b[i]-'a']<=r)                        

    
dp[j]=min(dp[j],nt[dp[j-1]+1][b[i]-'a']);//最早出现b[i]的位置是长度加1后最早结束的位置  
                 

    
if(dp[j]<=r)                       

lcs=max(lcs,j);//更新最大公共子串                 

}         
  }

printf("%d\n",r-l+1+m-2*lcs);        

  
}    

  }

 

}

猜你喜欢

转载自blog.csdn.net/Nefeertari/article/details/107605330
今日推荐