LA-3716(sort的神用)
题意:
给出两条长度均为n的NDA链A和B,找出一段最长的字串[l,r]使得该区域的突变位置不超过p%;
思路:
sum[i]表示[1,i]中不相同的个数,可得表达式(sum[i]-sum[j])/(i-j)<=p/100;
变换一下就是100*sum[i]-p*i<=100*sum[j]-p*j;
求出100*sum[i]-p*i后按这个sort,sort后得到的序列中,如果排在前边的i(sort前的编号)比后边的大,那么就表示这两个就是一个合法序列;对于每个i,找到排在它后面的最小值就是它能形成的最长的合法序列,从后往前扫一遍,同时更新最小值和答案;
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <stack> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++) #define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) { char CH; bool F=false; for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar()); for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar()); F && (num=-num); } int stk[70], tp; template<class T> inline void print(T p) { if(!p) { puts("0"); return; } while(p) stk[++ tp] = p%10, p/=10; while(tp) putchar(stk[tp--] + '0'); putchar('\n'); } const LL mod=1e9+7; const double PI=acos(-1.0); const int inf=1e9; const int N=15e4+10; const int maxn=1e3+10; const double eps=1e-6; int n,p; char s1[N],s2[N]; struct node{ int sum,id; }po[N]; int cmp(node x,node y) { if(x.sum==y.sum)return x.id>y.id; return x.sum<y.sum; } int main() { while(1) { read(n);read(p); if(!n&&!p)break; scanf("%s",s1); scanf("%s",s2); po[0].sum=0; For(i,0,n-1) { if(s1[i]!=s2[i])po[i+1].sum=po[i].sum+1; else po[i+1].sum=po[i].sum; } For(i,1,n)po[i].sum=po[i].sum*100-p*i,po[i].id=i; po[0].id=0; sort(po,po+n+1,cmp); int ans=0,temp=n+10; for(int i=n;i>=0;i--) { if(po[i].id>temp)ans=max(ans,po[i].id-temp); else temp=min(temp,po[i].id); } if(ans==0)cout<<"No solution."<<"\n"; else cout<<ans<<"\n"; } return 0; }