要在s串中找出子序列使其正过来和反过来的前缀同时都为t串。
首先能得出的结论就是,要让t成为前缀,那么肯定是要从正反s串中依次找到t串中每个字母的第一次出现的位置。从而符合要求的子串肯定是从这些第一次出现的位置开始往后拼接的。
前后找完之后观察,是否存在相交情况,不存在直接,计算子序列就行,如果从在通过马拉车找到包含t串末尾的回文串长度,这些长度可能就是前区间中用来交叉的长度
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define int long long
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
#define endl "\n"
#define pb push_back
#define pii pair<int, int>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9+7;
const int N = 1e6 + 20;
int n, m;
vector<int> manacher(string t) {//返回 包含字符串末尾的回文串 的长度
string s = "?#";
for (auto ch : t) {
s += ch;
s += '#';
}
s += '!';
vector<int> p(s.size()), len;
int mr = 0, mid = 0, ans = 0;
for (int i = 1; i + 1 < s.size(); i++) {
if (i <= mr) p[i] = min(p[mid * 2 - i], mr - i + 1);
else p[i] = 1;
while (s[i - p[i]] == s[i + p[i]]) p[i]++;
if (i + p[i] > mr) mr = i + p[i] - 1, mid = i;
if (i & 1) {
if (p[i] == 1) continue;
int l = p[i] / 2;
int id = (i - 1) / 2;
if (id + l >= t.size()) len.push_back(l * 2);
}
else {
int id = i / 2 - 1;
if (id + (p[i] - 1) / 2 + 1 >= t.size()) len.push_back(p[i] - 1);
}
}
return len;
}
inline int cal(string s){//本质不同非空子序列数量
int n=s.size();
s=" "+s;
vector<int>dp(n+1),lst(26);
for(int i=1;i<=n;i++){
dp[i]=dp[i-1];
if(!lst[s[i]-'a'])(dp[i]+=dp[i-1]+1)%=mod;
else (dp[i]+=(dp[i-1]-dp[lst[s[i]-'a']-1])%mod+mod)%=mod;
lst[s[i]-'a']=i;
}
return dp[n];
}
void solve()
{
cin >> n >> m;
string s,t;
cin >> s >> t;
auto len = manacher(t);
s=' '+s;t=' '+t;
vector<int>l,r;
for(int i=1,j=1;i<=n;i++)
{
if(s[i]==t[j] && j<=m)
{
l.push_back(i);
j++;
}
}
for(int i=n,j=1;i>=1;i--)
{
if(j<=m && s[i]==t[j])
{
r.push_back(i);
j++;
}
}
if(l.size()<m || r.size()<m)
{
cout << 0 <<endl;
return ;
}
int ans=0;
if(l[m-1] < r[m-1])//不交叉直接计算
{
string x="";
rep(i,l[m-1]+1,r[m-1]-1)x+=s[i];
ans+=cal(x)+1;//记得算是本身
}
for(auto it : len)
{
if(it==m)
{
ans++;
}else
{
ans+=(l[m-it-1]<r[m-1]);
}
// m-w-1 在前缀中减去用来交叉的长度
// 看剩下的前缀 l[0]->l[m-w-1] 能否与后缀拼接
}
cout << ans% mod<<endl;
}
signed main()
{
IOS
int t;
t = 1;
//cin >> t;
while(t -- )
{
solve();
}
return 0;
}