题意:
思路:
对于C在B*里面的,利用kmp来进行匹配,是否能成功统计下来;对于B在A中的,可以将B的所有的加入到AC自动机里面,同时统计当前的字符串结尾的位置,之后利用A跑一遍,跑过的路径上的点标记;最后如果当前字符串结尾的位置跑过,并且kmp匹配成功,就输出当前的序号
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,M=1e3+10;
const int mod=1e9+7;
int n,m,o;
int ne1[N],ne2[N],jk[N];
int v[N],in[N],idx,mp[N];
string s1,s2;
struct cs
{
int son[30],fail,flag,ans;
void clear()
{
memset(son,0,sizeof(son));
fail=flag=ans=0;
}
}tr[N];
queue<int>q;
void insert(string s,int num)
{
int u=1;
for(int i=0;s[i];i++)
{
int v=s[i]-'a';
if(!tr[u].son[v])tr[u].son[v]=++idx;
u=tr[u].son[v];
}
if(!tr[u].flag)tr[u].flag=num;//第几个输入进去的
mp[num]=tr[u].flag;
}
void getfail()
{
for(int i=0;i<26;i++)tr[0].son[i]=1;
q.push(1);
while(!q.empty())
{
int u=q.front();
q.pop();
int Fail=tr[u].fail;
for(int i=0;i<26;i++)
{
int v=tr[u].son[i];
if(!v)
{
tr[u].son[i]=tr[Fail].son[i];
continue;
}
tr[v].fail=tr[Fail].son[i];
in[tr[v].fail]++;
q.push(v);
}
}
}
void tp()
{
for(int i=1;i<=idx;i++)
{
if(in[i]==0)
q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
v[tr[u].flag]=tr[u].ans;
int v=tr[u].fail;
in[v]--;
tr[v].ans+=tr[u].ans;
if(in[v]==0)q.push(v);
}
}
void query(string s)
{
int u=1,len=s.size();
for(int i=0;i<len;i++)
{
u=tr[u].son[s[i]-'a'];
tr[u].ans++;
}
}
void df()
{
cin>>n;
cin>>s1>>s2;
idx=1;
int l2=s2.size();
s2=" "+s2;
for(int i=2,j=0;i<=l2;i++)
{
while(j&&s2[i]!=s2[j+1])j=ne2[j];
if(s2[i]==s2[j+1])j++;
ne2[i]=j;
}
for(int ii=1;ii<=n;ii++)
{
jk[ii]=0;
string a,b;
cin>>a>>b;
insert(a,ii);
int n2=b.size();
b=" "+b;
for(int i=1,j=0;i<=n2;i++)
{
while(j&&b[i]!=s2[j+1])j=ne2[j];
if(b[i]==s2[j+1])j++;
if(j==l2)
{
jk[ii]=1;
break;
}
}
}
getfail();
query(s1);
tp();
for(int i=1;i<=n;i++)
{
if(v[mp[i]]&&jk[i])cout<<i<<" ";
}
cout<<"\n";
for(int i=1;i<=idx;i++)tr[i].clear();//初始化,方便下次使用
}
signed main(){
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int t=1;
cin>>t;
while(t--)
{
df();
}
return 0;
}