jzoi4964
思路是先对每个(k-1)长度的子字符串之间建边,然后拓扑,若有环则最终仍有indg[i]为 0的
这题用字符串哈希的话会超时
以下是30分做法
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define mo 9223372036854775807 #define ll unsigned long long using namespace std; const int maxn=1e5+2; const int hx=2000000; int n,k,cnt,to[maxn],ans,head[maxn],nex[maxn],indg[hx],dis[hx]; char s[maxn]; bool vis[hx]; queue<int>q; ll hsh[hx]; ll ksm(int x,int y){ ll t=1; while(y){ if(y&1)t=t*x%mo; x=x*x%mo; y>>=1; } return t; } ll hash(ll x){ ll pos=x%hx; while(hsh[pos]&&hsh[pos]!=x)pos=(pos+1)%hx; hsh[pos]=x; return pos; } void addedge(int u,int v){ indg[v]++;vis[u]=vis[v]=1; to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt; } void topo(){ while(!q.empty()){ int u=q.front();q.pop(); ans=max(ans,dis[u]); for(int i=head[u];i;i=nex[i]){ int v=to[i]; dis[v]=max(dis[v],dis[u]+1); if(!(--indg[v]))q.push(v); } } } int main(){ while(~scanf("%d%d",&n,&k)){ ll kk=ksm(26,k-1); cnt=1; memset(head,0,sizeof(head)); memset(indg,0,sizeof(indg)); memset(vis,0,sizeof(vis)); while(n--){ scanf("%s",s+1); int len=strlen(s+1); if(len<k)continue; for(int i=1;i<=len;i++)s[i]=s[i]-'a'+1; ll t=0; for(int i=1;i<k;i++)t=t*26+s[i]; for(int i=k;i<=len;i++){ ll u=hash(t); t=t*26+s[i]-kk*s[i-k+1]; ll v=hash(t); addedge(u,v); } } ans=k-1; for(int i=0;i<hx;i++) if(vis[i]&&!indg[i]){q.push(i);dis[i]=k-1;} topo(); bool flag=0; for(int i=0;i<hx;i++)if(indg[i]){ flag=1;break; } if(flag)printf("INF\n");else printf("%d\n",ans); } }
满分用map
#include<cstdio> #include<string> #include<map> #include<queue> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn=1e5,hx=6e6; string s[maxn]; int n,k,ans,cnt,tot,nex[hx],head[hx],to[hx],dis[hx],vis[hx],indg[hx]; map<string,int>m; int hash(string ss){ int &pos=m[ss]; if(!pos)pos=++tot; return pos; } void addedge(int u,int v){ indg[v]++;to[++cnt]=v;nex[cnt]=head[u];head[u]=cnt; } queue<int>q; void topo(){ while(!q.empty()){ int u=q.front();q.pop(); ans=max(ans,dis[u]); for(int i=head[u];i;i=nex[i]){ dis[to[i]]=max(dis[to[i]],dis[u]+1); if(--indg[to[i]]==0) q.push(to[i]); } } } int main(){ while(~scanf("%d%d",&n,&k)){ cnt=tot=ans=0; memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); memset(indg,0,sizeof(indg)); m.clear(); for(int i=1;i<=n;i++){ cin>>s[i]; for(int j=0;j+k-1<s[i].size();j++){ addedge(hash(s[i].substr(j,k-1)),hash(s[i].substr(j+1,k-1))); } } for(int i=1;i<=tot;i++) if(!indg[i]) q.push(i); topo(); bool flag=0; for(int i=1;i<=tot;i++)if(indg[i]>0){flag=1;break;} if(flag)printf("INF\n");else printf("%d\n",ans+k-1); } }