1. 程式人生 > >【HDU 6103 Kirinriki】 & 尺取

【HDU 6103 Kirinriki】 & 尺取

Kirinriki

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 541 Accepted Submission(s): 204

Problem Description
We define the distance of two strings A and B with same length n is
disA,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.

Input
The 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
T≤100
0≤m≤5000
Each character in the string is lowercase letter, 2≤|S|≤5000
∑|S|≤20000

Output
For 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

Source
2017 Multi-University Training Contest - Team 6

題意 : 給出一串字串,從中選出兩個不重疊的字串,使得兩個字串的距離和 <= m 的最長字串長度,A,B 串中的字元距離計算為 disA,B=∑i=0n−1|Ai−Bn−1−i|

題解 :

兩個不重合的子串向中心一起延長會形成奇偶長度兩種合串。列舉一下中心向外延伸,如果和超過了閾值彈掉中心處的位置。雙指標維護。時間複雜度O(n^2)
另解:
列舉[1,i],[j,n]用同樣方法往內縮。
時間複雜度O(n^2)

思路 : 在總字串中依次挑選長度為 2 ~ nl 的子串,在滿足距離和 sum <= m 的前提下,從兩邊往裡縮排,正反各一次

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 5e3 + 10;
char s[MAX];
int nl,m,ans;
void solve(){
    for(int i = 2; i <= nl; i++){
        int o = i / 2,l = 0,n = 0,sum = 0;
        for(int j = 0; j < o; j++){
           sum += abs(s[j] - s[i - j - 1]); // 從兩邊往裡縮排
           if(sum <= m) n++,ans = max(ans,n);
           else{
                sum -= abs(s[l] - s[i - l - 1]);
                sum -= abs(s[j] - s[i - j - 1]);
                n--,j--,l++; // 一直到滿足條件在縮排
           }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %s",&m,s);
        nl = strlen(s),ans = 0;
        solve(),reverse(s,s + nl),solve(); // 正反各一遍
        printf("%d\n",ans);
    }
    return 0;
}