在 A 裡面找有 C 的 B

D06發表於2024-07-23

ios::sync_with_stdio(false);
cin.tie(0);

  • \(\Uparrow\) 關閉同步/解除繫結,可以最佳化讀入字串的效率
  • 這行程式碼的缺失,不僅導致程式在本地執行時需要過好幾秒才能讀入資料,更導致程式在OJ上評測時TLE
  • 時隔半年,自己還能獨自完成KMP和AC自動機的程式碼,還是比較開心的;除錯時,把握整體,注意模組的錯位
  • 要對字典樹的每個節點開一個動態陣列,以處理字串相同的情況
點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;
string a,c;
int t[100005][26],nx[100005],fail[100005];
bool ans[100005];
vector<int>id[100005];
string b1,b2;
void kmp()
{
	nx[1]=0;
	for(int i=2;i<=c.size();i++)
	{
		int j=nx[i-1];
		while(j!=0&&c[j]!=c[i-1])
		{
			j=nx[j];
		}
		nx[i]=j;
		if(c[j]==c[i-1])
		{
			nx[i]++;
		}
	}
	nx[c.size()+1]=0;
}
bool pd(char *s,int n)
{
	for(int i=c.size()+2;i<=n+c.size()+1;i++)
	{
		int j=nx[i-1];
		while(j!=0&&c[j]!=s[i-1-(c.size()+1)])
		{
			j=nx[j];
		}
		nx[i]=j;
		if(c[j]==s[i-1-(c.size()+1)])
		{
			nx[i]++;
		}
		if(nx[i]==c.size())
		{
			return true;
		}
	}
	return false;
}
int tot;
int q[100005],l,r;
void insert(string s,int tag)
{
	int p=0;
	for(int i=0;i<s.size();i++)
	{
		if(t[p][s[i]-'a']==0)
		{
			tot++;
			t[p][s[i]-'a']=tot;
			id[tot].clear();
		}
		p=t[p][s[i]-'a'];
	}
	id[p].push_back(tag);
}
void pre()
{
	l=1,r=0;
	for(int i=0;i<26;i++)
	{
		if(t[0][i]>0)
		{
			r++;
			q[r]=t[0][i];
		}
	}
	while(l<=r)
	{
		int n1=q[l];
		l++;
		for(int i=0;i<26;i++)
		{
			if(t[n1][i]==0)
			{
				t[n1][i]=t[fail[n1]][i];
			}
			else
			{
				fail[t[n1][i]]=t[fail[n1]][i];
				r++;
				q[r]=t[n1][i];
			}
		}
	}
}
void solve()
{
	int p=0;
	for(int i=0;i<a.size();i++)
	{
		p=t[p][a[i]-'a'];
		int q=p;
		while(q!=0)
		{
			for(int j=0;j<id[q].size();j++)
			{
				ans[id[q][j]]=true;
			}
			q=fail[q];
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		cin>>a>>c;
		tot=0;
		memset(fail,0,sizeof(fail));
		memset(t,0,sizeof(t));
		memset(id,0,sizeof(id));
		kmp(); 
		for(int i=1;i<=n;i++)
		{
			ans[i]=false;
			cin>>b1>>b2;
			if(pd(&b2[0],b2.size()))
			{
				insert(b1,i);
			}
		}
		pre();
		solve();
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(ans[i]==true)
			{
				cnt++;
				if(cnt!=1)
				{
					cout<<" ";
				}
				cout<<i;
			}
		}
		cout<<endl;
	}
	return 0;
}

相關文章