题目大意
- 给定两个字符串s和t,求出在s里面有多少个本质不同的子序列,使得该序列的前缀包含t,且该序列的反串也包含t
- 即 s的子序列=t+x+反t‘
首先要确定是否有,就是判断我的S字符串中有没有包含T字符串
for(l = 0 ; l < n ; l++) {
if(s[l] == t[num]) num++;
if(num == m) break;
}
if(num < m) {
cout << 0 << endl;
return 0;
}
其次如何求出子序列,因为子序列是可以跳着拿的,不是连续的,所以当出现一个新的字符加入,个数会有原有的x个变成x*2+1个,但如果说当前这个字符出现过了,我出现的个数是要减去我上一次出现该字符时的个数
void f1() {
for(int i = l + 1 ; i < r ; i++) {
if(vis[s[i]]) dp[i]=(dp[i-1]*2-dp[vis[s[i]]-1])%mod;
else dp[i] = (dp[i-1]*2+1)%mod;
vis[s[i]] = i;
}
ans = (dp[r-1]+1)%mod;
}
怎么把重叠部分算出我不太明白希望大佬评论一下
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
const int mod = 1e9+7;
const int A = 1e6+10;
int n,m,l,r,dp[A],vis[30],ans,p = 7;
string s,t;
void f1() {
for(int i = l + 1 ; i < r ; i++) {
if(vis[s[i]]) dp[i]=(dp[i-1]*2-dp[vis[s[i]]-1])%mod;
else dp[i] = (dp[i-1]*2+1)%mod;
vis[s[i]] = i;
}
ans = (dp[r-1]+1)%mod;
}
void f2(int x) {
int tx,ty,k;
tx = ty = 0;
k = 1;
for(int i = 0 ; i < m ; i++) {
tx = (tx * p + t[m - i - 1]) % mod;
ty = (t[m - i - 1] * k + ty) % mod;
k = k * p % mod;
if(tx == ty && i >= x - 1) ans++;
}
}
signed main() {
cin >> n >> m >> s >> t;
int num = 0;
for(l = 0 ; l < n ; l++) {
if(s[l] == t[num]) num++;
if(num == m) break;
}
if(num < m) {
cout << 0 << endl;
return 0;
}
num = 0;
for(r = n - 1 ; r > l ; r--) {
if(s[r] == t[num]) num++;
if(num == m) break;
}
if(l < r) f1();
f2(m-num);
cout << (ans + mod) % mod << endl;
return 0;
}
标签:vis,int,Reversed,Prefixes,++,num,Subsequences,dp,mod
From: https://blog.csdn.net/dhwujs/article/details/141323533