牛客寒假第六場 刪除子序列
阿新 • • 發佈:2022-03-13
刪除子序列
給出一個長度為nnn的字串SSS和一個長度為mmm的不含重複字元的字串TTT,每次你可以在SSS中刪除一個等於TTT的子序列,最多可以刪除多少次?
如字串S=ababccdS=ababccdS=ababccd,T=abcT=abcT=abc,可以選擇s1s2s5,s1s2s6,s1s4s5,s1s4s6,s3s4s5,s3s4s6s_1s_2s_5,s_1s_2s_6,s_1s_4s_5,s_1s_4s_6,s_3s_4s_5,s_3s_4s_6s1s2s5,s1s2s6,s1s4s5,s1s4s6,s3s4s5,s3s4s6進行刪除,刪除後分別得到abcd,abcd,bacd,bacd,abcd,abcdabcd,abcd,bacd,bacd,abcd,abcdabcd,abcd,bacd,bacd,abcd,abcd。
如果刪除後得到abcdabcdabcd,則還可以再進行一次刪除,最多可以刪除222次。
題意:
在字串中求定序的子序列的個數(不能重複)
思路:
我們可以一組一組的篩查
從t中最後一個字母開始,選一組,完成後繼續選,
想到用stack這個資料結構,從t中的最後一個字元的棧開始遍歷,必須滿足(前一個的最後棧頂元素小於後一個的棧頂元素),在完成pop一組的情況下計數,若某次沒有符合的元素了,就退出。
補充
怎麼使用map呢???
可以用vector 代替stack
ve.emplace_back(),ve.pop_back(),ve.back()
AC程式碼
#include<bits/stdc++.h> using namespace std; const int N=1e6+1; int dp[N][27]; void solve() { int n,m; char s[N],t[27]; cin>>n>>m; scanf("%s",s+1); scanf("%s",t+1); stack<int>st[m+1]; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(s[i]==t[j]) { st[j].push(i); break; } } } int ans=0; while(1) { int t=n+1; //t是用來比較的初始位置!取最大,因為t中最後一個元素不需要滿足什麼條件 for(int i=m;i>=1;i--) { while(!st[i].empty()&&st[i].top()>t) st[i].pop(); if(st[i].empty()) {cout<<ans<<endl;return;} t=st[i].top(); st[i].pop(); } ans++; } } signed main() { int t; cin>>t; while(t--) solve(); }