CF1295C Obtain the String
题意:
给出两个串s和t,每次操作可以选择s中的一个子序列拼到z串后,z串一开始是空的,询问至少操作几次可以使得z串变成t串
题解:
预处理思维题,我太菜了,这都不会做...
定义一个二维数组nxt,表示s中第i-1个字符后面要跟第j个字母的话,应该去哪个位置(比较难懂...)
然后先初始化所有边界值为-1
倒着遍历s串,预处理整个二维数组
然后遍历t串,定义一个指针同时遍历s串
如果对应二维数组的值存在,那么指针直接移到那个位置
否则次数加一,指针置为0
时间复杂度是O(26*M)=O(M)
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; string s,t; int T; int nxt[maxn][30]; int main () { scanf("%d",&T); while (T--) { cin>>s>>t; int len=s.length(); for (int i=0;i<26;i++) nxt[len][i]=-1; for (int i=len-1;i>=0;i--) { for (int j=0;j<26;j++) nxt[i][j]=nxt[i+1][j]; nxt[i][s[i]-'a']=i+1; } int ans=1; int tot=0; int f=1; for (int i=0;i<t.length();i++) { if (nxt[tot][t[i]-'a']!=-1) tot=nxt[tot][t[i]-'a']; else { ans++; tot=0; if (nxt[0][t[i]-'a']==-1) { f=0;break; } tot=nxt[tot][t[i]-'a']; } } if (!f) printf("-1\n"); else printf("%d\n",ans); } }