题目大意:
给你一个串s
再给你一个串t
问你有多少个s的子串中非连续包含t的有多少个
思路:
首先只有s中只有单个t的序列的时候
比如s=mmamm,t=a
这时候(a左边字母加+1)×(a右边字母+1)的时候就是结果
因为每个mma,ma,a都对应右边有两个字母
再加上左边连续子串数量3就是答案
那么如果出现多种t序列的时候呢?
比如s=mamam,t=a
这种时候对于第一个a的贡献是2×4
第二个是4×2
但这个时候会发现有子串有重叠串
就是mamam,mama,amam,ama重复计算了两次
这时候其实我们就能发现计算的时候把下个t的开头减去上个t的开头乘上末尾部分就是一个t的贡献
接来下就是枚举的事情啦
(比赛的时候例子写少了emmm,找不到感觉,麻了)
代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <string>
#include <math.h>
#include <string.h>
#include <cstdio>
#include <utility>
#define pf(x) (x)*(x)
#define lowerbit(x) x&(-x)
#define mid (l+r>>1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll mod=998244353;
string s;
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
string t;
cin>>s>>t;
int l=-1,r=-1;
int len1=s.size(),len2=t.size();
ll ans=0;
int st=-1;
while(1){
l=s.find(t[0],st+1);//从上个找到t的开头下标开始往下找
if(l==-1)break;//找不到就说明没有了
r=l;
for(int i=1;i<len2;i++){
r=s.find(t[i],r+1);
if(r==-1)break;
}
if(r==-1)break;
ans+=(l-st)*(len1-r);//(这个t的开头减去上个t的开头)乘上(字符串长度减去末尾)答案
st=l;
}
cout<<ans<<endl;
return 0;
}