题目大意:给出两条长度均为n的DNA链A和B,你的任务是找出一段最长的区域,使得该区域内的突变位置不超过p%
解题思路:设sum1为两条DNA链前i个不同基因的数量,sum2为两条DNA链前j个不同基因的数量(j > i),因为要满足公式(sum2-sum1) / (j-i) >= p / 100,由公式变形的 sum2 * 100 - p * j >= sum1 * 100 - p * i。再设和sum2*100-p*j相似的式子的计算结果为value,设置一个数组存放alue
1.如果当前的value < 前一个value,则将这个value放入数组
2.如果当前的value >= 前一个value,就找到一个在数组最左边且小于等于当前value的value值,这两个value的距离差就是结果
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 150010
char str1[maxn], str2[maxn];
int n, p, ans, cnt;
struct Point{
int id, sum, value;
}po[maxn], que[maxn];
int find(int num) {
int left = 0, right = cnt;
while(left < right) {
int mid = (left + right) / 2;
if(que[mid].value <= num)
right = mid;
else
left = mid + 1;
}
return que[left].id;
}
bool solve() {
ans = 0;
po[0].id = 0; po[0].sum = 0;po[0].value = 0;
que[0] = po[0];
cnt = 0;
for(int i = 1; i <= n; i++) {
po[i].id = i; po[i].sum = po[i-1].sum + (str1[i-1] != str2[i-1]);
po[i].value = p * i - po[i].sum * 100;
if(po[i].value < que[cnt].value)
que[++cnt] = po[i];
else {
int id = find(po[i].value);
ans = max(ans,po[i].id - id);
}
}
if(ans)
return true;
else
return false;
}
int main() {
while(scanf("%d%d",&n, &p) == 2 && n + p) {
scanf("%s%s",str1,str2);
if(solve())
printf("%d\n",ans);
else
printf("No solution.\n");
}
return 0;
}