Codeforces 762C Two strings(贪心)
题解:一道在别人口中很水的贪心题,然而在考试的时候就没有想到,只拿了50分。下文中a为第一个字符串,b为第二个字符串。
我们维护两个数组,一个是l[i],一个是r[i]。l[i]表示b[0...i]在a中按题意完全匹配(从前向后匹配)的最前的位置,r[i]表示b[i...lenb]按题意从后向前匹配的最后的位置。这两个数组其实具有单调性,可以O(len)求出。接着我们枚举i,表示b[0...i]留下来,假如有个j,满足l[i]<r[j],那么把b[i+1...j-1]移走是满足题目要求的。而且随着i的增大,可行的j只会向后移动!用指针一遍扫过即可。
#include<algorithm> #include<fstream> #include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; char c1[105020],c2[105020]; int l[105010],r[105010],len1,len2,x,y,z; void Work() { int p1=0,p2=0; while (p1<=len1&&p2<=len2) { while (p1<=len1&&c1[p1]!=c2[p2]) p1++; l[p2] = p1; p2++; p1++; } p1=len1,p2=len2; while (p1>=0&&p2>=0) { while (p1>=0&&c1[p1]!=c2[p2]) p1--; r[p2] = p1; p2--; p1--; } } int main() { freopen("1986.in","r",stdin); freopen("1986.out","w",stdout); scanf("%s",c1); scanf("%s",c2); len1 = strlen(c1)-1; len2 = strlen(c2)-1; for (int i=0; i<=len2; i++) l[i] = len1+1; for (int i=0; i<=len2; i++) r[i] = -1; Work(); z = len2; if (l[0]>len1) { printf("-\n"); return 0; } else { int p=1; for (int i=0; i<=len2; i++) { while (r[p]<=l[i]&&p<=len2) p++; if (l[i]>len1) break; if (z>p-i-1) { z=p-i-1; x=i; y=p; } if (z==0) break; } for (int i=0; i<=x; i++) printf("%c",c2[i]); for (int i=y; i<=len2; i++) printf("%c",c2[i]); } return 0; }