1. 程式人生 > 其它 >牛客多校第五場D Double Strings

牛客多校第五場D Double Strings

題意: 給定兩個字串A,B求長度相同的AB子串,使得子串的前面部分相等,且第一個不相等的位置B>A。求這樣的子串個數

場上把兩個DP寫反了,應該先求前面部分相等的種數,再對於後半部分的大於DP

思路:f[i][j]表示A的前i個字元與B的前j個字元能組成多少相等的子串。

若AB不相等,f[i][j]=f[i--1][j]+f[i][j-1]-f[i-1][j-1];

若AB相等,f[i][j]額外加上f[i-1][j-1],表示一定帶有當前這兩個字元的相等子串

求完f之後再利用f求解

dp[i][j]表示A前i個字元與B前j個字元的解數。

dp[i][j]=dp[i-1][j]+dp[i][j-1] (原來一直覺得這裡要減掉一個dp[i-1][j-1]後來問了別人才知道因為這裡如果前面i-1,j-1的子串是符合條件的,那麼這裡i與j無論放什麼都沒有關係,所以還要加回去,就正好抵消了)

如果b[j]>a[i] dp[i][j]額外加上f[i-1][j-1]

下附程式碼:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 char a[5005],b[5005];
 5 int dp[5005][5005],f[5005][5005];
 6 ll res=0;
 7 const int mod=1e9+7;
 8 int main(){
 9     scanf("%s%s",a+1,b+1);
10     int n=strlen(a+1),m=strlen(b+1);
11
memset(f,0,sizeof(f)); 12 f[0][0]=1; 13 for (int i=1; i<=m; i++) f[0][i]=1; 14 for (int i=1; i<=n; i++) f[i][0]=1; 15 for (int i=1; i<=n; i++){ 16 for (int j=1; j<=m; j++){ 17 f[i][j]=((f[i-1][j]+f[i][j-1])%mod-f[i-1][j-1]+mod)%mod; 18 if (a[i]==b[j]){
19 f[i][j]=(f[i-1][j-1]+f[i][j])%mod; 20 } 21 } 22 } 23 for (int i=1; i<=n; i++){ 24 for (int j=1; j<=m; j++){ 25 dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod; 26 if (a[i]<b[j]) dp[i][j]=(dp[i][j]+f[i-1][j-1])%mod; 27 } 28 } 29 printf("%lld",dp[n][m]); 30 }
View Code