1. 程式人生 > >Codeforces 191A - Dynasty Puzzles - [DP]

Codeforces 191A - Dynasty Puzzles - [DP]

clu nbsp 一個 set 字母相同 ont eof string 字符串

題目鏈接:https://codeforces.com/problemset/problem/191/A

題意:

給出 $n$ 個小寫字母組成的字符串,兩個字符串如果前者的最後一個字母與後者的首字母相同,那麽兩者可以連接,

同時要求最後得到的一個長字符串的首尾字母也要相同,求最長的滿足要求的字符串的長度是多少。

題解:

這個DP蠻有意思的。

記 $f[x][y]$ 為從第一個字符串到當前字符串,字母 $x$ 到字母 $y$ 的最長字符串的長度。

這樣,對於當前的字符串 $s_i$,狀態轉移可以枚舉 $k = a \sim z$,維護 $f[k][y] = \max(f[k][y], f[k][x]+|s_i|)$。

由於枚舉字符串是從 $s_1$ 到 $s_n$ 的,所以可以確保組合起來時的順序是正確的,狀態轉移也是正確的。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int n;
string s[maxn];
int f[30][30];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];

    memset(f,
-1,sizeof(f)); for(int i=0;i<=z-a;i++) f[i][i]=0; for(int i=1;i<=n;i++) { int x=s[i].front()-a, y=s[i].back()-a; for(int k=0;k<=z-a;k++) { if(f[k][x]==-1) continue; f[k][y]=max(f[k][y],f[k][x]+(int)s[i].size()); } }
int res=0; for(int i=0;i<=z-a;i++) res=max(res,f[i][i]); cout<<res<<endl; }

PS.動態規劃的題還是要多刷,見識更多的套路,有助於開闊思路。

Codeforces 191A - Dynasty Puzzles - [DP]