楼上已经提到了字符串同构,我这里也有个好玩的解法。
就是对原始串求哈希值,然后对这串字符串直接滚动,可以知道求解所有字符串的同构字符串的哈希值的复杂度为 。
为字符串长度。其中因为存在对大数进行存储的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;
} 
京公网安备 11010502036488号