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