1. 程式人生 > >字符串(string.cpp)

字符串(string.cpp)

fin line 矩陣 每次 cdc fine 思路 include 設置

字符串(string.cpp)

神TM字符串DP

題目描述:

小林和亮亮正在做一個遊戲。小林隨意的寫出一個字符串,字符串僅由大寫字母組成,然後指定一個非負整數m,亮亮可以進行至多m次操作。每次操作為交換相鄰的兩個字符。亮亮的目標是使得操作後的字符串出現最長相同的字符的長度最大。你的任務是計算這個最大長度是多少。

樣例輸入:

ABCCDCDDC
4

樣例輸出:

4

思路:

設置一個字符串長度x26大小的二維數組,對於字符串中的每個字母,記錄其出現的位置,將對應的矩陣元素設置為1,其余元素為0,然後按列優先遍歷矩陣,將每個字母出現的位置下標記錄到一個數組裏,計算將i和j之間的相同元素全部移動到一起需要的最小移動次數,在這個最小次數滿足滿足約束條件的前提下,篩選出最大的連續字母的個數。最後比較所有字母的最大連續個數,輸出其中的最大值即可。

CODE:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

#define N 26
#define M 5050
 
using namespace std;

string s;
int a[M][N],m;//a是矩陣,出現字母的地方都置1
int f[M],num[M]; //f[i]是存放各字母在滿足約束的情況下最大的連續數

int dp(int i , int j , int*a) {
    if(i == j) return 0;
    else if(i + 1 == j) return a[j] - a[i] - 1;
    else return dp(i + 1 , j - 1 , a) + a[j] - a[i] - (j - i);
}
inline void init() {
    memset(a,0,sizeof(a) );
    memset(f,0,sizeof(f) );
    memset(num,0,sizeof(num) );
}
inline void open_judge() {
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
}

int main() {
    //open_judge();
    cin>>s;
    scanf("%d",&m);
    init();
    int len = s.length();
    for(int i = 0 ; i < len ; i++) {
        for(int j = 0 ; j < 26 ; j++) {
            a[i][s[i] - 'A'] = 1;
        }
    }
    for(int j = 0 ; j < 26 ; j++) {
        int k = 0;
        for(int i = 0 ; i < len;i++) {
            if(a[i][j] == 1) num[k++] = i;
        }
        if(k == 1) f[j] = 1;
        else {
            int temp = -1;
            for(int i = 0 ; i < k ; i++) {
                for(int l = i + 1 ; l < k ; l++) {
                    if( dp(i , l , num) <= m ) {
                        if((l - i) + 1 > temp)
                            temp = (l - i) + 1;
                    }
                }
            }
            f[j] = temp;
        }
    }
    sort(f , f + N);
    printf("%d\n",f[N-1]);
    return 0;
}

字符串(string.cpp)