本题需要的前置知识:hash/kmp+ACAM,解法很简单,没有什么好补充的,不过可以学习一下std的写法,构建fail树,再跑一遍dfs累积答案,这样的做法比较高效,不过我写kmp+ac自动机会TLE,估计可能是STL的锅,hash就快很多
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int maxn = 1e6+10;
int tr[maxn][26], cnt;
int exist[maxn];
int fail[maxn];
int sum[maxn];
vector<int>g[maxn];
struct trie{
inline int insert(const string &s){
int p = 0;
for(char ch:s){//从索引0开始到结尾
int c = ch-'a';//只能处理全是小写字母,要普适需修改
if(!tr[p][c]) tr[p][c] = ++cnt;
p = tr[p][c];
}
return p;
}
inline void build() {
queue<int> q;
for (int i = 0; i < 26; i++){
if(tr[0][i]) q.push(tr[0][i]);
}
while(!q.empty()){
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++) {
if(tr[u][i]){
fail[tr[u][i]] = tr[fail[u]][i];//儿子存在,建回跳边
q.push(tr[u][i]);
}else tr[u][i] = tr[fail[u]][i];//建转移边
}
}
for(int i = 1;i<=cnt;++i){
g[fail[i]].push_back(i);
}
}
};
inline void dfs(int x){
for(auto y:g[x]){
dfs(y);
sum[x]+=sum[y];
}
}
const int mod1 = 1e9+7,mod2 = 998244353;
const int b1 = 37,b2 = 233;
int p1[maxn],p2[maxn];
int h1[maxn],h2[maxn];
inline int get1(int l,int r){
return (1LL*h1[r]-1LL*h1[l-1]*p1[r-l+1]%mod1+mod1)%mod1;
}
inline int get2(int l,int r){
return (1LL*h2[r]-1LL*h2[l-1]*p2[r-l+1]%mod2+mod2)%mod2;
}
int n;
inline void solve(){
cin>>n;
vector<pair<string,string>> a(n);
string A,C;
cin>>A>>C;
int r1 = 0,r2 = 0;
for(int i = 0;i<C.size();++i){
r1 = (1LL*r1*b1%mod1+C[i]-'a'+1LL)%mod1;
r2 = (1LL*r2*b2%mod2+C[i]-'a'+1LL)%mod2;
}
pair<int,int> c = {r1,r2};
trie t;
for(int i = 0;i<n;++i){
cin>>a[i].first>>a[i].second;
h1[0] = h2[0] = 0;
for(int j = 1;j<=a[i].second.size();++j){//索引从0开始要往后移一格
h1[j] = (1ll * h1[j - 1] * b1 % mod1 + a[i].second[j-1] - 'a' + 1LL) % mod1;
h2[j] = (1ll * h2[j - 1] * b2 % mod2 + a[i].second[j-1] - 'a' + 1LL) % mod2;
}
bool flag = 0;
for(int j = 1;j+C.size()-1<=a[i].second.size();++j){
int l1 = get1(j,j+C.size()-1),l2 = get2(j,j+C.size()-1);
pair<int,int> tmp = {l1,l2};
if(tmp==c){
flag = 1;
break;
}
}
if(flag){
exist[i] = t.insert(a[i].first);//每个点节点位置的编号
}
}
t.build();
int u = 0;
for(auto i:A){
u = tr[u][i-'a'];
sum[u]++;
}
dfs(0);
for (int i = 0;i<n ;i++) {
if (exist[i] && sum[exist[i]] > 0) {
cout<<i+1<<" ";
}
}
cout<<"\n";
for(int i = 0;i<n;++i) exist[i] = 0;
for(int i = 0;i<=cnt;++i){
sum[i]=0;
fail[i]=0;
memset(tr[i],0,sizeof tr[i]);
g[i].clear();
}
cnt=0;
}
signed main(){
ios;
p1[0]=p2[0]=1;
for(int i = 1;i<=1e5+10;++i){
p1[i] = 1LL*p1[i-1]*b1%mod1;
p2[i] = 1LL*p2[i-1]*b2%mod2;
}
int t;cin>>t;
while(t--){
solve();
}
return 0;
}