先用map处理字符串每个元素,然后用数组储存
要求不相同的所有组合,我们反着来求
x = a(第一个字符串能构成的所有的组合序列)+b(第二个字符串能构成的所有的组合序列) - c(两个字符串中的相同组合序列)*2
a = 2^n(第一个字符串的元素个数)-1;同理b;(很煞笔的用组合公式求2333,后来反应过来也没有改了)
dp[i][j]代表以a字符串中的第i个元素为组合序列的最后一个元素,以b字符串中的第j个元素为组合序列的最后一个元素,相同组合序列的个数
sum[i][j]代表a字符串中前i个元素,b字符串中前j个元素,能构成的所有相同组合序列的个数之和
每次求得一个dp[i][j],就用去更新,树状数组
在利用树状数组求得sum[i][j]
/******************************************** Author :Crystal Created Time : File Name : ********************************************/ #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> #include <cstring> #include <climits> #include <string> #include <vector> #include <cmath> #include <stack> #include <queue> #include <set> #include <map> #include <sstream> #include <cctype> using namespace std; typedef long long ll; typedef pair<int ,int> pii; #define MEM(a,b) memset(a,b,sizeof a) #define CLR(a) memset(a,0,sizeof a); const int inf = 0x3f3f3f3f; const int MOD = 10000007; //#define LOCAL ll c[3001][3001]; int dp[2001][2001]; int sum[2001][2001]; int ans1[2001]; int ans2[2001]; int k1,k2; void init(){ for(int i=0;i<=2001;i++){ //c[0][i] = 1; c[i][0] = 1; } for(int i=1;i<=2001;i++){ for(int j=1;j<=i;j++){ c[i][j] = (c[i][j] + c[i-1][j-1]+c[i-1][j])%MOD; } } } map<string,int> mp; int cc[2001][2001], n; int Lowbit(int t) return t&(t^(t-1)); } int Sum(int x,int y) { ll sum = 0; for(int i=x;i>0;i-=Lowbit(i)){ for(int j=y;j>0;j-=Lowbit(j)){ sum = (sum +cc[i][j])%MOD; } } return sum; } void add(int x, int y,int val) { for(int i=x;i<=k1;i+=Lowbit(i)){ for(int j=y;j<=k2;j+=Lowbit(j)){ cc[i][j] = (val + cc[i][j])%MOD; } } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif init(); int t;cin >> t; int kase = 1; while(t--){ CLR(cc); CLR(sum); CLR(dp); mp.clear(); char a[4001]; char b[4001]; scanf("%s%s",a,b); int la = strlen(a); int lb = strlen(b); int cnt = 0; k1 = 0; k2 = 0; for(int i=0;i<la;i++){ string tmp; if(a[i] <= 'Z' && a[i] >= 'A'){ tmp += a[i]; while(i+1 <la && a[i+1] <= '9' && a[i+1] >= '0'){ tmp += a[i+1]; i++; } if(!mp[tmp]){ mp[tmp] = ++cnt; } //cout << mp[tmp] << endl; ans1[++k1] = mp[tmp]; } } for(int i=0;i<lb;i++){ string tmp; if(b[i] <= 'Z' && b[i] >= 'A'){ tmp += b[i]; while(i+1<lb && b[i+1] <= '9' && b[i+1] >= '0'){ tmp += b[i+1]; i++; } if(!mp[tmp]){ mp[tmp] = ++cnt; } ans2[++k2] = mp[tmp]; } } n = k1*k2+k2; for(int i=1;i<=k1;i++){ for(int j=1;j<=k2;j++){ if(ans1[i]==ans2[j]){ dp[i][j] = (dp[i][j]+sum[i-1][j-1]+1)%MOD; add(i,j,dp[i][j]); } sum[i][j] = Sum(i,j); } } ll ssum = 0; for(int i=1;i<=k1;i++){ ssum = (c[k1][i]+ssum)%MOD; } for(int i=1;i<=k2;i++){ ssum = (c[k2][i]+ssum)%MOD; } cout << "Case " << kase++ << ':' << ' '; cout << (ssum - sum[k1][k2]*2 +MOD*2)%MOD << endl; } return 0; }