2 条题解

  • -1
    @ 2026-1-9 11:06:25

    你说得对,但 AC 自动机相当好用。

    数据结构,没有思维,只有硬来。

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1e6+10;
    const int M = 510;
    int _;
    int t[N][30];
    int fail[N];
    int n;
    string s[M];
    int ed[M],sum[N];
    int tot;
    vector<int> e[N];
    int ins(string s);
    void clean(int pos);
    void clear();
    void build();
    void build_tree();
    void dfs(int x);
    void query(string s);
    int ins(string s)
    {
    	int u=0;
    	for(auto i:s)
    	{
    		int p=i-'a'+1;
    		if(!t[u][p])
    		{
    			t[u][p]=++tot;
    			clean(tot);
    		}
    		u=t[u][p];
    	}
    	return u;
    }
    void solve()
    {
    	cin>>n;
    	tot=0;clean(0);
    	for(int i=1;i<=n;i++)
    	{
    		cin>>s[i];
    		ed[i]=ins(s[i]);
    	}
    	build();
    	build_tree();
    	for(int i=n;i;i--)
    	{
    		clear();
    		query(s[i]);
    		dfs(0);
    		for(int j=1;j<=i;j++)
    		{
    			if(!sum[ed[j]])
    			{
    				cout<<i<<'\n';
    				return;
    			}
    		}
    	}
    	cout<<-1<<'\n';
    }
    int main()
    {
    	cin>>_;
    	while(_--) solve();
    	return 0;
    }
    void clean(int pos)
    {
    	for(int i=1;i<=26;i++) t[pos][i]=0;
    	fail[pos]=0;
    }
    void clear()
    {
    	for(int i=0;i<=tot;i++) sum[i]=0;
    }
    void build()
    {
    	queue<int> q;
    	for(int i=1;i<=26;i++)
    		if(t[0][i])
    			q.push(t[0][i]);
    	while(q.size())
    	{
    		int u=q.front();
    		q.pop();
    		for(int i=1;i<=26;i++)
    		{
    			if(t[u][i])
    			{
    				fail[t[u][i]]=t[fail[u]][i];
    				q.push(t[u][i]);
    			}
    			else
    			{
    				t[u][i]=t[fail[u]][i];
    			}
    		}
    	}
    }
    void query(string s)
    {
    	int u=0;
    	for(auto i:s)
    	{
    		int c=i-'a'+1;
    		u=t[u][c];
    		sum[u]++;
    	}
    }
    void dfs(int x)
    {
    	for(auto i:e[x])
    	{
    		dfs(i);
    		sum[x]+=sum[i];
    	}
    }
    void build_tree()
    {
    	for(int i=0;i<=tot;i++) e[i].clear();
    	for(int i=1;i<=tot;i++)
    	{
    		 e[fail[i]].push_back(i);
    		//  cout<<fail[i]<<' '<<i<<'\n';
    	}
    }
    
    • -1
      @ 2025-4-18 16:58:52

      有一定的思维含量。

      我们注意到如果一个串 TT 为另一个串 SS 的子串,这个字符串就严格不如 SS ,于是我们就可以维护一个类似于单调栈的东西,如果一个字符串不能把栈里所有字符串都杀掉,就把它扔去和答案取 maxmax

      代码省略

      • 1

      信息

      ID
      167
      时间
      1000ms
      内存
      256MiB
      难度
      6
      标签
      (无)
      递交数
      32
      已通过
      11
      上传者