1. 程式人生 > >Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

oid ans src puts clas 全部 char 字符串包含 test

題目鏈接:Educational Codeforces Round 21 G. Anthem of Berland

題意:

給你兩個字符串,第一個字符串包含問號,問號可以變成任意字符串。

問你第一個字符串最多包含多少個第二個字符串。

題解:

考慮dp[i][j],表示當前考慮到第一個串的第i位,已經匹配到第二個字符串的第j位.

這樣的話復雜度為26*n*m*O(fail).

fail可以用kmp進行預處理,將26個字母全部處理出來,這樣復雜度就變成了26*n*m。

狀態轉移看代碼(就是一個kmp過程),感覺寫得有點亂。- -!

技術分享
 1 #include<bits/stdc++.h>
 2
#define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 char s[N],t[N]; 7 int s_len,t_len,now,nxt[N]; 8 int dp[2][N],Nxt[26][N]; 9 10 void kmp_pre(char x[], int m, int nxt[]) { 11 int i, j; j = nxt[0] = -1; i = 0; 12 while (i<m) { 13 while
(-1 != j && x[i] != x[j])j = nxt[j]; 14 nxt[++i] = ++j; 15 } 16 } 17 18 int main() 19 { 20 scanf("%s%s",s,t); 21 s_len=strlen(s),t_len=strlen(t); 22 if(s_len<t_len)return puts("0"),0; 23 kmp_pre(t,t_len,nxt); 24 F(j,0,25)F(k,0,t_len-1) 25 { 26 int idx=k;
27 while(idx!=-1&&(j+a)!=t[idx])idx=nxt[idx]; 28 Nxt[j][k]=idx; 29 } 30 now=0; 31 F(j,0,t_len-1)dp[now][j]=-1; 32 dp[now][0]=0; 33 F(i,0,s_len-1) 34 { 35 F(j,0,t_len-1)dp[now^1][j]=-1; 36 if(s[i]==?) 37 { 38 F(j,0,25)F(k,0,t_len-1)if(dp[now][k]>=0) 39 { 40 int idx=k,val=dp[now][k]; 41 if(idx!=-1&&(j+a)!=t[idx])idx=Nxt[j][idx]; 42 while(idx!=-1&&(j+a)!=t[idx])idx=nxt[idx]; 43 idx++; 44 if(idx>=t_len)val++,idx=nxt[idx]; 45 dp[now^1][idx]=max(dp[now^1][idx],val); 46 } 47 } 48 else F(k,0,t_len-1)if(dp[now][k]>=0) 49 { 50 int idx=k,val=dp[now][k]; 51 if(idx!=-1&&s[i]!=t[idx])idx=Nxt[s[i]-a][idx]; 52 while(idx!=-1&&s[i]!=t[idx])idx=nxt[idx]; 53 idx++; 54 if(idx>=t_len)val++,idx=nxt[idx]; 55 dp[now^1][idx]=max(dp[now^1][idx],val); 56 } 57 now^=1; 58 } 59 int ans=0; 60 F(k,0,t_len)ans=max(ans,dp[now][k]); 61 printf("%d\n",ans); 62 return 0; 63 }
View Code

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)