日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Double Strings

發(fā)布時(shí)間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Double Strings 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Double Strings

題意:

給你s和t兩個(gè)字符串,在其中選出兩個(gè)等長(zhǎng)的子序列(可以不連續(xù))a,b,滿足a的字典序嚴(yán)格小于b的字典序,問(wèn)方案數(shù),答案mod(1e9+7)

題解:

好的方案的構(gòu)成是一段相同的前綴+一個(gè)不同的字符(a比b小)+長(zhǎng)度相同的任意后綴,按照這樣構(gòu)造一定是合法且包含所有情況
我們用dp[i][j]表示只考慮A的前i個(gè)字符和B的前j個(gè)字符時(shí)的相同的子序列的個(gè)數(shù)(有點(diǎn)類似于最長(zhǎng)公共子序列,不過(guò)我們這里記錄的是方案數(shù))
轉(zhuǎn)移方程可得:dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1](加上之前的情況減去重復(fù)的)
當(dāng)a[i]=b[j]時(shí),dp[i][j]=dp[i-1][j-1]+1
現(xiàn)在是如何求長(zhǎng)度相同的任意后綴,我們假設(shè)A中剩余長(zhǎng)度是x,B中剩余長(zhǎng)度位y,設(shè)x<=y,那么求長(zhǎng)度相同的任意后綴,就是A和B中分別取i個(gè)(i最大到x),有:∑i=0xCxiCyi=∑i=0xCxx?iCyi=Cx+yx\sum_{i=0}^{x}C_{x}^{i}C_{y}^{i}=\sum_{i=0}^{x}C_{x}^{x-i}C_{y}^{i}=C_{x+y}^{x}i=0x?Cxi?Cyi?=i=0x?Cxx?i?Cyi?=Cx+yx?
每步推導(dǎo)過(guò)程都是用的常規(guī)組合數(shù)公式變換

代碼:

#include<bits/stdc++.h> #define debug(a,b) printf("%s = %d\n",a,b); using namespace std; typedef long long ll; typedef pair<int, int> PII; //Fe~Jozky const ll INF_ll=1e18; const int INF_int=0x3f3f3f3f; inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w; } void rd_txt(){#ifdef ONLINE_JUDGE#elsefreopen("in.txt","r",stdin);#endif } const int maxn=1e6+9; const int mod=1e9+7; ll fac[maxn]; ll inv[maxn]; ll dp[6000][6000]; char s[maxn],t[maxn]; int C(int n,int m) {if(n<m) {return 0;}return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod; } ll poww(ll a,ll b){ll ans=1;while(b){if(b&1){ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans; } void init() {fac[0]=1;int N=1e6;for(int i=1;i<=N;i++) {fac[i]=1LL*fac[i-1]*i%mod;}inv[N-1]=poww(fac[N-1],mod-2);for(int i=N-2;i>=0;i--) {inv[i]=1LL*inv[i+1]*(i+1)%mod;} } int main() {init();scanf("%s%s",s+1,t+1);int n=strlen(s+1),m=strlen(t+1);for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%mod;if(s[i]==t[j]) {dp[i][j]=(dp[i][j]+dp[i-1][j-1]+1)%mod;}dp[i][j]=(dp[i][j]+mod)%mod;}}ll ans=0;for(int i=1;i<=n;i++) {for(int j=1;j<=m;j++) {if(s[i]<t[j]) {ans=(ans+1LL*(dp[i-1][j-1]+1)*C(n-i+m-j,n-i))%mod;}}}cout<<ans<<endl;return 0; }

總結(jié)

以上是生活随笔為你收集整理的Double Strings的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。