【YbtOJ#20235】公共序列
阿新 • • 發佈:2020-12-01
題目
題目連結:https://www.ybtoj.com.cn/contest/66/problem/3
\(|A|\leq 10^6,|B|\leq 10^3\)。
思路
直接設 \(f[i][j]\) 表示兩個串分別匹配到第 \(i,j\) 位的方法已經行不通了。但是因為 \(|B|\leq 10^3\),所以可以在這裡考慮一下。
設 \(f[i][j]\) 表示 \(B\) 串前 \(i\) 位匹配了其中 \(j\) 位,在 \(A\) 串中至少要匹配掉前多少位。
那麼假設 \(B[i]\) 在 \(f[i-1][j-1]\) 後面下一個可以匹配到的位置是 \(k\),顯然
然後在所有 \(f[i][j]<+\infty\) 中取 \(j\) 的最大值即可。
時間複雜度 \(O(n^2\log m)\)。
程式碼
#include <bits/stdc++.h> using namespace std; const int N=1010,M=1000010; int n,m,ans,f[N][N]; char s[N],t[M]; vector<int> pos[27]; int main() { freopen("lcs.in","r",stdin); freopen("lcs.out","w",stdout); scanf("%s%s",t+1,s+1); n=strlen(s+1); m=strlen(t+1); for (int i=1;i<=m;i++) pos[t[i]-'a'+1].push_back(i); for (int i=1;i<=26;i++) pos[i].push_back(2e9); memset(f,0x3f3f3f3f,sizeof(f)); f[0][0]=0; for (int i=1;i<=n;i++) for (int j=0;j<=i;j++) { int k=*upper_bound(pos[s[i]-'a'+1].begin(),pos[s[i]-'a'+1].end(),f[i-1][j-1]); f[i][j]=min(f[i-1][j],k); if (f[i][j]<=m) ans=max(ans,j); } printf("%d",ans); return 0; }