Description
Input
Output
Sample Input
Sample Output
Data Constraint
分析
如果两个操作区间有交集,那么可以把它们合并。(容易证明)
n,m较小,可以设f[i][j] 表示从S和T的第i、j个位置开始最多能匹配多少位。直接计算会超时,因此考虑dp
对于S的一个位i,用l[i],r[i]表示它所在的操作区间的两个边界(如果它不被包含,则视作它被[i..i]包含,即l[i]=r[i]=i)。
对于一个公共子串S[i..i+len],它可能跨过很多个操作区间。设它跨过k个区间,那么第2——k-1个区间都是全部匹配的,最后一个匹配了若干位,第1个匹配了r[i]-i+1个字符。而且确定了第一个区间从T串的哪里开始匹配,就可以推出其它区间的了。
那么我们可以设g[i][j],表示由i (i==l[i]) 开始的区间,T串从j开始,能匹配多少个字符。O(nm)即可预处理出。
然后对于f[i][j],只要用g[i][j]判断是否能匹配到g[i][j],如果可以就从f[r[i]+1][r[i]+1+j-i]转移过来即可。
时间复杂度 O(nm)
dp主要部分
for (int i=0;i<n;i++) if (l[i]==i)
{
memset(cnt,0,sizeof(cnt));
int j;
for (j=i;l[j]==i;j++) cnt[S[j]]++;
for (j=0;j<m && cnt[T[j]];j++) cnt[T[j]]--;
g[i][0]=j;
for (int k=1;k<m;k++)
{
if (j>=k) cnt[T[k-1]]++;else j=k;
for (;j<m && cnt[T[j]];j++) cnt[T[j]]--;
g[i][k]=j-k;
}
}
for (int i=n-1;i>=0;i--)
for (int j=0;j<m;j++)
if (g[l[i]][j]+i-1<r[i] || g[l[i]][j]+i==m) f[i][j]=g[l[i]][j];else
f[i][j]=f[r[i]+1][r[i]+1+j-i]+r[i]-i+1;