洛古 P2679 子串 題解
阿新 • • 發佈:2019-05-04
ble 分區 滾動 一個 ostream 字符 xor運算 math https
P2679 子串
題目描述
首先設f[i][j][p]
表示在\(A\)串中選\(i\)個字符被劃分為\(k\)段匹配\(B\)串中的\(j\)個字符方案數,但是發現還不夠,因為當前選還是不選的\(k\)轉移取決於上個字符選沒有選沒。所以我們再設一維狀態\(0/1\)表示當前字符選或者不選的方案數。
轉移:1.如果a[i]==b[j]
,
f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1]; 這一位不拿,不累加j-1的合法狀態 f[i][j][p][1]=f[i-1][j-1][p][0]+f[i-1][j-1][p-1][1]+f[i-1][j-1][p][1]; f[i-1][j-1][p][0] 最後一位不匹配,必須重新劃分區間,必須從p中轉,不累加p-1的合法狀態 f[i-1][j-1][p-1][1] 最後一位匹配,但不重新劃分區間,必須從p-1中轉,累加p-1的合法狀態 f[i-1][j-1][p][1] 最後一位匹配,重新劃分一個區間,p不變,直接中轉
2.如果a[i]!=b[j]
,
f[i][j][p][0]=f[i-1][j][p][0]+f[i-1][j][p][1];
同上
f[i][j][p][1]=0 因為字符不同無法匹配,所以直接為0
初始化
for (int i=0;i<=n;i++)
f[i][0][0][0]=f[i][0][0][1]=1;
不管i選幾個讓B串中匹配的數為0的只有一種,就是什麽都不選
f[0][0][0][0]和f[0][0][0][1]也要初始化,因為中轉要用到
70分
#include<iostream> #include<cstring> #include<cstdio> #define ll long long using namespace std; const int N=510,M=51,mod=1e9+7; char a[N],b[M]; int f[N][M][M][2]; int n,m,k; int main() { scanf("%d%d%d",&n,&m,&k); scanf("%s%s",a+1,b+1); for (int i=0;i<=n;i++) f[i][0][0][0]=1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int p=1;p<=k;p++) if (a[i]==b[j]) { f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod; f[i][j][p][1]=((ll)f[i-1][j-1][p][1]+f[i-1][j-1][p-1][0]+f[i-1][j-1][p-1][1])%mod; } else { f[i][j][p][0]=((ll)f[i-1][j][p][0]+f[i-1][j][p][1])%mod; f[i][j][p][1]=0; } printf("%d\n",(f[n][m][k][1]+f[n][m][k][0])%mod); return 0; }
因為數據比較大,直接\(DP\)會\(MLE\),但是我們觀察發現,每次中轉只用到i-1和i,所以我們用滾動數組來代替第一維
初始設now=1,因為1對xor運算無影響
now^1就相當於i-1,因為1^1=0,0^1=1,所以實現了數組的滾動。
最後輸出n^1,如果n是單數,肯定滾動到1,偶數滾動到0,所以判斷奇偶。
100分
#include<iostream> #include<cstring> #include<cstdio> #define ll long long using namespace std; const int N=1010,M=210,mod=1e9+7; char a[N],b[M]; int f[2][M][M][2]; int n,m,k; bool now=1; int main() { scanf("%d%d%d",&n,&m,&k); scanf("%s%s",a+1,b+1); f[0][0][0][0]=f[1][0][0][0]=1; now=1; for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) for (int p=1;p<=k;p++) if (a[i]==b[j]) { f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod; f[now][j][p][1]=((ll)f[now^1][j-1][p][1]+f[now^1][j-1][p-1][0]+f[now^1][j-1][p-1][1])%mod; } else { f[now][j][p][0]=((ll)f[now^1][j][p][0]+f[now^1][j][p][1])%mod; f[now][j][p][1]=0; } now^=1; } printf("%d\n",(f[n&1][m][k][1]+f[n&1][m][k][0])%mod); return 0; }
洛古 P2679 子串 題解