先给一个串 t
再给 n 个串 s
将俩 s 拼接 (可以相同)
求 t 中有多少个这样的串 的和
我们把问题转化为这样
对于
把他分割成两部分
也就是求设前半部分的后缀是多少个S乘以后半部分的前缀是多少个S的和
我们看样例 1
1*2
2*1
1*1
所以答案就是5
将字符串转置,这两个问题也就是一个问题
利用后缀自动机处理
pos [ i ] 代表着字符串的第 i 位在SAM中对应的状态 也就是前 i+1位的状态( 前缀 )
cnt [ i ] 代表着在状态 i 下的 有多少个后缀是 S
对于每一个字符串S 如果存在 计算贡献
parent 树上 拓扑排序 从树的顶点 向下累加传递
然后对于t中每一个前缀去乘以反转后的前缀
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
struct SAM
{
int trans[maxn<<1][26],slink[maxn<<1],maxlen[maxn<<1];
int last,now,root,len;
int indegree[maxn<<1],rank[maxn<<1];
int pos[maxn<<1];
int cnt[maxn<<1];
int flag=0;
void newnode(int v)
{
maxlen[++now]=v;
}
void extend(int c)
{
newnode(maxlen[last]+1);
int p=last,np=now;
while(p&&!trans[p][c])
{
trans[p][c]=np;
p=slink[p];
}
if(!p)
slink[np]=root;
else
{
int q=trans[p][c];
if(maxlen[p]+1!=maxlen[q])
{
newnode(maxlen[p]+1);
int nq=now;
memcpy(trans[nq],trans[q],sizeof(trans[q]));
slink[nq]=slink[q];
slink[q]=slink[np]=nq;
while(p&&trans[p][c]==q)
{
trans[p][c]=nq;
p=slink[p];
}
}
else
slink[np]=q;
}
last=np;
pos[flag]=np;
flag++;
}
void build(string s)
{
root=last=now=1;
memset(trans,0,sizeof(trans));
memset(cnt,0,sizeof(cnt));
memset(pos,0,sizeof(pos));
memset(slink,0,sizeof(slink));
memset(maxlen,0,sizeof(maxlen));
len=s.size();
for(int i=0;i<len;++i)
extend(s[i]-'a');
}
void topsort()
{
for(int i=1;i<=now;++i)
indegree[maxlen[i]]++;
for(int i=1;i<=now;++i)
indegree[i]+=indegree[i-1];
for(int i=1;i<=now;++i)
rank[indegree[maxlen[i]]--]=i;
}
void f(string t)
{
int tp=root;
for(int i=0;i<t.length();i++)
{
if(trans[tp][t[i]-'a'])
{
tp=trans[tp][t[i]-'a'];
}
else
return;
}
cnt[tp]++;
}
void solve()
{
topsort();
for(int i=1;i<=now;i++)
{
cnt[rank[i]]+=cnt[slink[rank[i]]];
}
}
}sam,rsam;
int main()
{
string s,t;
cin>>s;
sam.build(s);
reverse(s.begin(),s.end());
rsam.build(s);
int n;
scanf("%d",&n);
while(n--)
{
cin>>t;
sam.f(t);
reverse(t.begin(),t.end());
rsam.f(t);
}
sam.solve();
rsam.solve();
ll ans=0;
for(int i=0;i<s.length()-1;i++)
{
ans+=(ll)sam.cnt[sam.pos[i]]*rsam.cnt[rsam.pos[s.length()-i-2]];
}
printf("%lld\n",ans);
return 0;
}