bzoj1633 / P2875 [USACO07FEB]牛的詞匯The Cow Lexicon
阿新 • • 發佈:2018-12-04
重疊 ide max tar https str output pan ble
P2875 [USACO07FEB]牛的詞匯The Cow Lexicon
三維dp
它慢,但它好寫。
直接根據題意設三個狀態:
$f[i][j][k]$表示主串掃到第$i$個字母,匹配到第$j$個單詞的第$k$位可以留下的最多字符數
當該位不選時,就傳遞上一位的數據$f[i][j][k]=f[i-1][j][k]$
當該位可以匹配時:
$if(a[i]==b[j][k]\&\&f[i-1][j][k-1])$
$f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+1);$
註意不允許有重疊單詞所以要判斷前一位
當匹配完一個單詞時,就要跳到一個新單詞的第一位上,那麽:
$f[i][j][1]=max(f[i][j][1],f[i-1][u][len[u]]+1)$
最後用主串的長度減去可留下字符數就是答案了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int max(int &a,int &b){return a>b?a:b;} 6 int m,n,f[305][605][30],len[605],ans; 7 char a[305],b[605View Code][30]; 8 void output(int x){//debug 9 cout<<"x:"<<x<<endl; 10 for(int i=1;i<=m;++i,cout<<endl) 11 for(int j=1;j<=len[i];++j) 12 cout<<f[x][i][j]<<" "; 13 cout<<endl<<endl; 14 } 15 int main(){ 16 scanf("%d%d",&m,&n); scanf("%s",a+1); 17 for(int i=1;i<=m;++i) 18 scanf("%s",b[i]+1),len[i]=strlen(b[i]+1); 19 for(int i=1;i<=n;++i) 20 for(int j=1;j<=m;++j){ 21 for(int k=1;k<=len[j];++k){ 22 f[i][j][k]=f[i-1][j][k]; 23 if(a[i]==b[j][k]&&f[i-1][j][k-1]) 24 f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+1); 25 } 26 if(a[i]==b[j][1]) 27 for(int u=1;u<=m;++u) 28 f[i][j][1]=max(f[i][j][1],f[i-1][u][len[u]]+1); 29 } 30 for(int i=1;i<=m;++i) ans=max(ans,f[n][i][len[i]]); 31 printf("%d",strlen(a+1)-ans); 32 cout<<endl; 33 return 0; 34 }
bzoj1633 / P2875 [USACO07FEB]牛的詞匯The Cow Lexicon