楼上已经提到了字符串同构,我这里也有个好玩的解法。
就是对原始串求哈希值,然后对这串字符串直接滚动,可以知道求解所有字符串的同构字符串的哈希值的复杂度为 为字符串长度。其中因为存在对大数进行存储的map,总的求所有字符串归属集合的复杂度为 。当然你也可以弄个小点的模数,然后限定在数组可达的范围内就可以不需要带 了。
具体做法先预处理出 的模数的累乘,然后在求滚动哈希值时,考虑去掉当前所在字符的影响,然后整体乘模数,再在后面加上当前字符即可。具体可以自己理解下求哈希的原理。
至于后面的复杂度就是 的了。记得多组数据得初始化彻底,不然泪两行。

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<cstring>
#include<map>

using namespace std;
typedef unsigned long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;

ll ex[maxn];
int dfn[maxn],low[maxn],col[maxn],vis[maxn],cnt,tmp;
int ct[maxn];
int n,m,u,v,now,ans;
vector<int>ed[maxn],mc[maxn];
map<ll,int>mp;
stack<int>sta;

void tarjan(int x)
{
    dfn[x]=low[x]=++cnt;
    sta.push(x); vis[x]=1;
    for(auto y:ed[x])
    {
        if(!dfn[y])
        {
            tarjan(y); 
            low[x]=min(low[x],low[y]);
        }
        else if(vis[y])
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        tmp++; int p;
        do{
            p=sta.top(); sta.pop();
            col[p]=tmp; vis[p]=0;
        }while(x!=p);
    }
    return;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    ex[0]=1; for(int i=1;i<=1e5;i++)ex[i]=ex[i-1]*mod;
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
        {
            dfn[i]=low[i]=vis[i]=col[i]=ct[i]=0;
            ed[i].clear(); mc[i].clear();
        }
        mp.clear(); cnt=ans=now=tmp=0;
        for(int i=1;i<=n;i++)
        {
            string s; ll hs=0; int flag=0; cin>>s; 
            for(int j=0;j<s.length();j++)hs=hs*mod+s[j];
            for(int j=0;j<s.length();j++)
            {
                hs=hs-s[j]*ex[s.length()-1];
                hs=hs*mod+s[j];
                if(mp.find(hs)!=mp.end())
                {
                    flag=1; break;
                }
            }
            if(flag)mc[mp[hs]].push_back(i);
            else mp[hs]=++now,mc[now].push_back(i);
        }
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v; ed[u].push_back(v);
        }
        for(int i=1;i<=n;i++)
        {
            if(!dfn[i])tarjan(i);
        }
        for(int i=1;i<=now;i++)
        {
            for(auto j:mc[i])ans=max(ans,++ct[col[j]]);
            for(auto j:mc[i])ct[col[j]]=0;
        }
        cout<<ans<<endl;
    }
    return 0;
}