codeforces 1203 D2 Remove the Substring (hard version)
依然在补题。。。
链接:https://codeforces.com/problemset/problem/1203/D2
题意:给定一个母串和一个子串,求在母串中删掉一个最长连续数列的同时保证在剩余母串里能找到子串(可以不连续但不能顺序颠倒)
解法:是codeforces上摸来的解法,我只是一个无情的解读机:做两个数组li与ri,分别储存字串在母串中第一次和最后一次出现时该字符对应的位置,比如样例1: b b a b a
他们的位置分别为 0 1 2 3 4
而字串: b b
对应li数组: 0 1
对应ri数组: 1 3
为什么要选这样两个特殊位置,就要考虑到我们最后会挖掉的字符串的位置无非三种:在某个包含字串的连续串左边,在某个包含字串的连续串右边或是在之中间。那么显然,前两种情况的最大值肯定出现在最右字串和最左字串上,而为了求出第三种情况的最大值,我们希望在最边缘的地方找到组合成字串的字符。。。也就是把最右字串和最左字串两头组合起来。
代码如下:
1 #include<set> 2 #include<stdio.h> 3 #include<string.h> 4 #include<math.h> 5 #include<vector> 6 #include<stdlib.h> 7 #include<queue> 8 #include<algorithm> 9 #include<map> 10 #include<stack> 11 using namespace std; 12 char a[200005]; 13 char c[200005]; 14 int li[200005];//字串中每个字符出现的最左 15 int ri[200005];//字串中每个字符出现的最右 16 int main() 17 { 18 scanf("%s",a); 19 scanf("%s",c); 20 int la=strlen(a); 21 int lc=strlen(c); 22 if(la==lc) 23 { 24 printf("0\n"); 25 } 26 else 27 { 28 int i=0; 29 int j=0; 30 while(i<lc) 31 { 32 if(a[j]==c[i]) 33 { 34 li[i]=j; 35 i++; 36 } 37 j++; 38 } 39 i=lc-1; 40 j=la-1; 41 while(i>-1) 42 { 43 if(a[j]==c[i]) 44 { 45 ri[i]=j; 46 i--; 47 } 48 j--; 49 } 50 int maxx=max(ri[0],la-li[lc-1]-1);//最右串左侧和最左串右侧 51 for(i=0;i<lc-1;i++) 52 { 53 maxx=max(maxx,ri[i+1]-li[i]-1);//中镂 54 } 55 printf("%d\n",maxx); 56 } 57 return 0; 58 }