题解 P3082 【[USACO13MAR] Necklace G】
upd on 25.10.30: 修改代码中小错误,感谢 @chenzhaoxu2027指出问题
Solution
正难则反,将问题转化成留下一个长度最长的
设
考虑从
其中
之后问题的难点就在于如何快速的求出每一个
记
先对
综上有:
初值:
时间复杂度
code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
const int maxm = 1e3 + 5;
int n,m,f[maxn][maxm],ans,g[maxm][30],kmp[maxm];
char a[maxn],b[maxm];
void input()
{
scanf("%s%s",a + 1,b + 1);
n = strlen(a + 1),m = strlen(b + 1);
}
void prefix()
{
int j = 0;
for(int i = 2;i <= m;i++)
{
while(j&&b[i] != b[j + 1])
j = kmp[j];
kmp[i] = b[i] == b[j + 1] ? ++j : 0;
}
for(int i = 0;i < m;i++)
for(int j = 1;j <= 26;j++)
g[i][j] = (b[i + 1] == j + 'a' - 1) ? i + 1 : g[kmp[i]][j];
}
void DP()
{
for(int i = 0;i < n;i++)
{
if(i)
for(int j = 0;j <= m;j++)
f[i][j] = max(f[i][j],f[i - 1][j]);
for(int j = 0;j < m;j++)
f[i + 1][g[j][a[i + 1] - 'a' + 1]] = max(f[i + 1][g[j][a[i + 1] - 'a' + 1]],f[i][j] + 1);
}
}
void output()
{
for(int i = 0;i < m;i++)
ans = max(ans,f[n][i]);
printf("%d",n - ans);
}
int main()
{
input();
prefix();
DP();
output();
return 0 ;
}