string 字串拆分 二維dp(斜率優化)

2021-08-01 09:19:51 字數 2330 閱讀 6460

【題目描述】

有乙個的字串s需要拆分成k個串,每乙個串需要花費一些代價來維護。對於乙個串,其維護的代價為第i個字元在模式串p中的位置pos的(i – pos) * pos之和。現在需要計算出k個串的最小維護代價。

【輸入格式】

第一行乙個字串p和乙個整數k。

第二行乙個字串s。

【輸出格式】

一行,最小維護代價。

【樣例輸入】

abcdefghijklmnopqrstuvwzyx 3

aabbbccccccccc

【樣例輸出】

2 【資料範圍】

對於30%的資料 k <= 100,|s| <= 100;

對於100%的資料 1 <= k <= 500,1 <= |s| <= 20000, 模式串p中不存在相同的兩個的字元,所有字元都是小寫字母。

【樣例說明】

拆成「aabbb」,「cccc」和「ccccc」,6->(0 + 0 + 1 + 2 + 3), -4->(-4 -2 + 0 + 2) 和 0->(-4 -2 + 0 + 2 + 4)。

思路 f[i][j]=f[k][j-1]+(sum[i]-sum[k])-(1+k)*(sump[i]-sump[k])

用sump表示(pos[k + 1] + pos[k + 2] + … + pos[i])的字首和

用sum表示(k * pos[k + 1] + (k + 1) * pos[k + 2] + … + (i - 1) * pos[i] )的字首和

f[k][j-1]+(sum[i]-sum[k])是不分段的答案

分段後k+1 ~ i左移了k+1個單位,針對每乙個位置,減少了(k+1)*pos

所以這個轉移方程還是比較合理的

設u < v

u比v優的條件是

(f[u][j-1] - sum[u] + (u+1)*sump[u]) - (f[v][j-1] - sum[v] + (v+1)*sump[v]) < (u-v)*sump[i]

有一點要注意的就是這是個二維的dp,由於j存在於關係式當中,會影響最優的比較,所以選擇維護多個佇列維護最優。

承接前幾道斜率優化的練習,不打詳解了,參照斜率優化

#include 

#include

#include

#include

#include

#define ll long long

using namespace std;

const int n = 20010;

ll pos[n], s[n], sum[n], sump[n], sumpp[n], f[n][510], q[n][510];

int head[510], tail[510];

int idc;

int pointx(int u, int v)

ll pointy(int u, int v, int j)

int main()

scanf("%d

%c", &k, &cc);

idc = 0;

while(scanf("%c", &cc))

n = idc - 1;

for(int i=1; i<=n; i++)

}printf("%d\n", f[n][k]);

return

0; }

上面這個**不太優,仔細想一想就會發現在我們for迴圈轉移時,可以變為j在外層,i在內層,這樣j在轉移方程的問題就得到解決了,j++時q陣列就可以清空了。這樣就不需要二維的q

**如下

#include

#include

#define clear(a) memset(a,0,sizeof(a));

using namespace std;

const int maxn=20001;

char str[maxn],p[maxn];

int dp[maxn][501],sum[maxn],pos[maxn];

int sump[maxn],q[maxn],h,t;

int lens,lenp,k,j;

inline int up(int k,int p)

inline int down(int k,int p)

inline void sum_init()

}int main()

}printf("%d",dp[lens-1][k]);

return

0;}

非筆者親筆

ps:初始化腦抽,生無可戀【攤手

字串hash Matrix(二維)

給定乙個m行n列的01矩陣 只包含數字0或1的矩陣 再執行q次詢問,每次詢問給出乙個a行b列的01矩陣,求該矩陣是否在原矩陣 現過。第一行四個整數m,n,a,b。接下來乙個m行n列的01矩陣,數字之間沒有空格。接下來乙個整數q。接下來q個a行b列的01矩陣,數字之間沒有空格。對於每個詢問,輸出1表示...

二維陣列 字串 API

1 二維陣列 陣列中的元素,又指向乙個新的子陣列 何時使用 1.儲存橫行豎列的資料時 2.分組儲存上下級包含關係時 如何建立 1.先建立空陣列,再初始化元素為子陣列 var data data 0 0,0,0,0 data 1 0,0,0,0 何時使用 不確定子陣列的個數或內容時 2.建立時就初始化...

二維陣列 字元陣列與字串

要求 了解多維陣列的概念 掌握二維陣列的使用 掌握用字元陣列存放字串的方法 掌握字串的輸入及輸出方法 二維陣列的定義 例 int a 2 3 定義乙個二維陣列 該陣列有2行3列共6個元素 這6個元素都存放int型資料 儲存時先儲存第一行的3個元素,然後再儲存第二行的3個元素 可將此二維陣列看成是乙個...