1. 程式人生 > >HDU - 6103 :Kirinriki(不錯的尺取法)

HDU - 6103 :Kirinriki(不錯的尺取法)

 

We define the distance of two strings A and B with same length n is
diA,=∑ i=n|n1disA,B=∑i=0n−1|Ai−Bn−1−i|
The difference between the two characters is defined as the difference in ASCII.
You should find the maximum length of two non-overlapping substrings in given string S, and the distance between them are less then or equal to m.

InputThe first line of the input gives the number of test cases T; T test cases follow.
Each case begins with one line with one integers m : the limit distance of substring.
Then a string S follow.

Limits
T100 T≤100
0m5000 0≤m≤5000
Each character in the string is lowercase letter,

2≤|S|≤5000">2|S|5000 2≤|S|≤5000
|S|20000 ∑|S|≤20000
OutputFor each test case output one interge denotes the answer : the maximum length of the substring.
Sample Input

1
5
abcdefedcb

Sample Output

5


        
 

Hint

[0, 4] abcde
[5, 9] fedcb
The distance between them is abs('a' - 'b') + abs('b' - 'c') + abs('c' - 'd') + abs('d' - 'e') + abs('e' - 'f') = 5

題意:給堵一個字串,求最長的兩個不相交字串S、T,其字串值之差小於M,輸出這個長度。

思路:尺取法,列舉起點終點發現沒法做,我們列舉S和T的對稱點,然後根據對稱點尺取。即每次右邊界++,維護左邊界,使其滿足小於M。

主要是利用了此題中,字串之差是首尾倒序做差,我們我們可以這樣處理。  有點像求迴文串一樣。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
char c[5050]; int T,N,M,ans;
void solve()
{
    rep(i,1,N){
        int L=1,R=0,tmp=0;
        while(i+R+1<=N&&i-R-1>=1){
            R++; tmp+=abs(c[i+R]-c[i-R]);
            while(tmp>M) tmp-=abs(c[i+L]-c[i-L]),L++;
            if(tmp<=M) ans=max(ans,R-L+1);
        }
    }
    rep(i,2,N){
        int L=1,R=0,tmp=0;
        while(i+R<=N&&i-1-R>=1){
            R++; tmp+=abs(c[i-1+R]-c[i-R]);
            while(tmp>M) tmp-=abs(c[i-1+L]-c[i-L]),L++;
            if(tmp<=M) ans=max(ans,R-L+1);
        }
    }
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%s",&M,c+1); N=strlen(c+1);
        ans=0; solve();
        printf("%d\n",ans);
    }
    return 0;
}