题目链接: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 ",ans); 62 return 0; 63 }