好位置(思维)
链接:https://ac.nowcoder.com/acm/problem/15870
来源:牛客网
题目描述
给出两个串s和x
定义s中的某一位i为好的位置,当且仅当存在s的子序列y=sk1sk2....sk|x|(1<=k1<k2<...<k|x|<=|s|)y=sk1sk2....sk|x|(1<=k1<k2<...<k|x|<=|s|) 满足y=x且存在j使得i=kj成立。
问s中是否所有的位置都是好的位置。
定义s中的某一位i为好的位置,当且仅当存在s的子序列y=sk1sk2....sk|x|(1<=k1<k2<...<k|x|<=|s|)y=sk1sk2....sk|x|(1<=k1<k2<...<k|x|<=|s|) 满足y=x且存在j使得i=kj成立。
问s中是否所有的位置都是好的位置。
输入描述:
一行两个字符串s,x,这两个串均由小写字母构成。
1 <= |s|, |x| <= 200000
输出描述:
Yes表示是。No表示不是。
具体思路:
pre[i]代表字符串x的前缀中,以s[i]结尾的子串中,字符串s从1~i中所能包含的以s[i]结尾的子串的最长长度。
suf[i]代表字符串x的后缀中,以s[i]开头的子串中,字符串s从i~len(s)中所能包含的以s[i]结尾的子串的最长长度。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define ll long long
4 # define inf 0x3f3f3f3f
5 const int maxn = 2e5+100;
6 int pre[maxn],suf[maxn];
7 char str1[maxn],str2[maxn];
8 int vis[maxn];
9 int main()
10 {
11 scanf("%s",str1+1);
12 scanf("%s",str2+1);
13 int len1=strlen(str1+1);
14 int len2=strlen(str2+1);
15 int pos=1,ans=0;
16 for(int i=1; i<=len1; i++)
17 {
18 if(str1[i]==str2[pos]&&pos<=len2)
19 {
20 ans++;
21 pos++;
22 vis[str1[i]]=ans;
23 pre[i]=ans;
24 }
25 else
26 {
27 pre[i]=vis[str1[i]];
28 }
29 }
30 memset(vis,0,sizeof(vis));
31 pos=len2,ans=0;
32 for(int i=len1; i>=1; i--)
33 {
34 if(str1[i]==str2[pos]&&pos>=1)
35 {
36 ans++;
37 pos--;
38 vis[str1[i]]=ans;
39 suf[i]=ans;
40 }
41 else
42 {
43 suf[i]=vis[str1[i]];
44 }
45 }
46 int flag=1;
47 for(int i=1; i<=len1; i++)
48 {
49 // printf("%d %d %d\n",i,pre[i],suf[i+1]);
50 if(pre[i]+suf[i]<len2)flag=0;
51 }
52 if(flag)
53 printf("Yes\n");
54 else printf("No\n");
55 return 0;
56 }