您的位置:首页 > 其它

【JZOJ4964】【GDKOI2017模拟1.21】Rhyme

2017-01-21 20:13 330 查看

Description

由于多次交换邮票没有满足所有人的需求,小Z被赶出了集邮部。无处可去的小Z决定加入音乐部,为了让音乐部的人注意到自己的才华,小Z想写一首曲子。为了让自己的曲子更好听,小Z找到了一些好听曲子作为模板。曲谱可以表示成只包含小写字母的字符串,小Z希望自己最终的曲谱中任意一个长度为K的子串都是一个模板的子串。现在小Z想知道自己的曲谱最长可以是多长,如果可以无限长的话请输出INF。

Data Constraint

对于30%的数据:K=2。

对于70%的数据:每组数据字符串总长不超过1000。

对于100%的数据:每组数据字符串总长不超过100000,1≤K≤100000。每个测试点数据不超过10组。dbhfdf

Solution

这道题其实很好想,难的是优化。我们将相邻的两个长度为k-1的子串连一条长度为1的边,判断一下有没有环,没有就输出最长路。

怎么做呢?考场上我想出了用spfa判环和最长路。但这显然是不行的!我们考虑换一种算法。

我们想到一个同样可以判环的工具:拓扑排序,而且这是O(N)的。同时,由于所有边的权值均为1,最后使点x的入度为0的点y一定是到达x的最远点。所以用拓扑排序一样能求出最长路。

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
#define ul unsigned long long
using namespace std;
const int maxn=4e5+7,maxn1=1e5+5;
ul first[maxn],last[2*maxn],next[2*maxn];
ul d[maxn];
ul v[maxn],fa[maxn],bz[maxn];
char s[maxn1];
ul h[maxn],a[maxn1],er[maxn1];
ul n,m,i,t,j,k,l,x,y,z,num,bz1,ans;
void lian(ul x,ul y){
last[++num]=y;next[num]=first[x];first[x]=num;
}
ul hash(ul x){
ul t=(x%maxn+maxn)%maxn;
while (h[t] && h[t]!=x) t=(t+1)%maxn;
h[t]=x;return t;
}
void spfa(){
int i,j=0,x,t;
for (i=1;i<=v[0];i++)
if (!fa[v[i]] && !bz[v[i]]) v[++j]=v[i],d[v[i]]=0,bz[v[i]]=1;
i=0;
while (i<j){
x=v[++i];
for (t=first[x];t;t=next[t]){
fa[last[t]]--;
if (!fa[last[t]]) d[last[t]]=d[x]+1,v[++j]=last[t];
}
}
}
int main(){
freopen("data.in","r",stdin);//freopen("rhyme.out","w",stdout);
er[0]=1;
for (i=1;i<maxn1;i++)
er[i]=er[i-1]*27;
while (scanf("%u",&n)!=EOF){
scanf("%u\n",&m);
memset(h,0,sizeof(h));memset(bz,0,sizeof(bz));
memset(first,0,sizeof(first));memset(fa,0,sizeof(fa));
num=0;v[0]=0;ans=0;
for (i=1;i<=n;i++){
scanf("%s\n",s+1);l=strlen(s+1);
for (j=1;j<=l;j++)
a[j]=a[j-1]*er[1]+s[j]-96;
for (j=m;j<=l;j++){
y=a[j]-a[j-m+1]*er[m-1];
t=hash(y);
y=a[j-1]-a[j-m]*er[m-1];
k=hash(y);lian(k,t);fa[t]++;
if (j==m) v[++v[0]]=k;
}
}
bz1=0;
spfa();
for (i=0;i<maxn;i++){
if (h[i]) ans=max(ans,d[i]);
if (h[i] && fa[i]) break;
}
if (bz1|| i!=maxn || m<=1) printf("INF\n");
else ans+=m-1,printf("%u\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: