12省联考???蒟蒻的试炼地,神犇的修罗场。
[十二省联考2019]字符串问题
看代码吧,网上好多题解。主要是记录一下自己的sb错误(调了快3h。码力有所下降啊,关键是谁知道sort内部啥原理啊。。。)
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define In(i) (i*2-1) 4 #define Out(i) (i*2) 5 using namespace std; 6 const int maxn=2e5+5; 7 int fst[maxn<<3],nxt[maxn<<6],to[maxn<<6],edge_count,id[maxn<<3]; 8 int w[maxn<<6]; 9 inline void add(int x,int y,int z){ 10 edge_count++; 11 to[edge_count]=y; 12 nxt[edge_count]=fst[x]; 13 fst[x]=edge_count; 14 w[edge_count]=z; 15 id[y]++; 16 /* if(edge_count<0 || edge_count>=(maxn<<6) || x<0 || y<0 || x>=(maxn<<3) || y>=(maxn<<3)){ 17 printf("GGGGGGGG"); 18 exit(0); 19 }*/ 20 } 21 int last,size,pos[maxn],cnt; 22 struct Node{ 23 int trans[30]; 24 int parent,mx; 25 Node(){ 26 parent=mx=0; 27 memset(trans,0,sizeof trans); 28 } 29 }t[maxn<<1]; 30 inline void sam_init(){ 31 t[0].parent=-1; 32 size=t[0].mx=last=0; 33 memset(t[0].trans,0,sizeof t[0].trans); 34 } 35 inline void extend(int x){ 36 int np=++size,p=last; 37 t[np].mx=t[p].mx+1;memset(t[np].trans,0,sizeof t[np].trans); 38 while(!t[p].trans[x] && p!=-1){ 39 t[p].trans[x]=np; 40 p=t[p].parent; 41 } 42 if(p==-1)t[np].parent=0; 43 else{ 44 int q=t[p].trans[x]; 45 if(t[q].mx==t[p].mx+1)t[np].parent=q; 46 else{ 47 int nq=++size; 48 t[nq]=t[q]; 49 t[nq].mx=t[p].mx+1; 50 t[q].parent=t[np].parent=nq; 51 while(p!=-1 && t[p].trans[x]==q){ 52 t[p].trans[x]=nq; 53 p=t[p].parent; 54 } 55 } 56 } 57 last=np; 58 } 59 LL dis[maxn<<3]; 60 int inque; 61 queue<int>q; 62 inline void topological_sort(){ 63 while(q.size())q.pop(); 64 memset(dis,0,sizeof dis); 65 inque=0; 66 LL ans=0; 67 for(int i=0;i<=cnt;i++) 68 if(!id[i]){ 69 q.push(i); 70 inque++; 71 } 72 while(q.size()){ 73 int u=q.front();q.pop(); 74 ans=max(ans,dis[u]); 75 for(int i=fst[u];i;i=nxt[i]){ 76 int v=to[i]; 77 dis[v]=max(dis[v],dis[u]+w[i]); 78 id[v]--; 79 if(!id[v]){ 80 q.push(v); 81 inque++; 82 } 83 } 84 } 85 printf(inque<=cnt ? "-1\n" : "%lld\n",ans); 86 } 87 int T,n; 88 char ch[maxn]; 89 int na,la[maxn],ra[maxn],ga[maxn],gb[maxn],nb,lb[maxn],rb[maxn],m; 90 struct substr{ 91 int len; 92 int isa; 93 int num; 94 substr(int Len=0,int Isa=false,int Num=0):len(Len),isa(Isa),num(Num){} 95 inline bool operator<(const substr &S)const{ 96 return ( len<S.len || ( len==S.len && isa<S.isa) ); 97 } 98 }; 99 vector<substr> V[maxn<<1]; 100 int f[maxn<<1][25]; 101 inline void clear(){ 102 memset(fst,0,sizeof fst); 103 memset(id,0,sizeof id); 104 //memset(f,0,sizeof f); 105 for(int i=0;i<=size;i++)V[i].clear(); 106 edge_count=0; 107 } 108 int main(){ 109 scanf("%d",&T); 110 while(T--){ 111 sam_init(); 112 scanf("%s",ch+1); 113 n=strlen(ch+1); 114 for(int i=n;i;i--)extend(ch[i]-'a'),pos[i]=last; 115 for(int i=0;i<=size;i++){ 116 f[i][0]=t[i].parent; 117 //printf("%d pa%d\n",i,t[i].parent); 118 //for(int j=0;j<26;j++)if(t[i].to[j])printf("%d %d\n",j,t[i].to[j]); 119 } 120 for(int i=1;i<=20;i++)for(int j=0;j<=size;j++) 121 f[j][i]=( f[j][i-1]==-1 ? -1 : f[f[j][i-1]][i-1] );//,printf("%d %d %d\n",j,i,f[j][i]); 122 cnt=(size<<1); 123 scanf("%d",&na); 124 for(int i=1;i<=na;i++){ 125 scanf("%d%d",&la[i],&ra[i]); 126 ra[i]=(ra[i]-la[i]+1); 127 la[i]=pos[la[i]]; 128 for(int j=20;j>=0;j--)if(f[ la[i] ][j]!=-1 && t[ f[la[i]][j] ].mx>=ra[i])la[i]=f[ la[i] ][j]; 129 //printf("%d\n",la[i]); 130 V[la[i]].push_back(substr(ra[i],1,++cnt)); 131 ga[i]=cnt; 132 } 133 scanf("%d",&nb); 134 for(int i=1;i<=nb;i++){ 135 scanf("%d%d",&lb[i],&rb[i]); 136 rb[i]=(rb[i]-lb[i]+1); 137 lb[i]=pos[lb[i]]; 138 for(int j=20;j>=0;j--)if(f[ lb[i]][j]!=-1 && t[ f[lb[i]][j] ].mx>=rb[i])lb[i]=f[ lb[i] ][j]; 139 //printf("%d\n",lb[i]); 140 V[lb[i]].push_back(substr(rb[i],0,++cnt)); 141 gb[i]=cnt; 142 } 143 for(int i=1;i<=size;i++){ 144 add(Out(t[i].parent),In(i),0); 145 add(In(i),Out(i),0);//in -> out 146 sort(V[i].begin(),V[i].end()); 147 /* 148 !!!??? sort 出shit了??? 149 认真的分析一下究竟是为什么我调了将近3h, 150 sort函数在比较的时候,必须要有< or cmp函数的bool 151 返回值,但本人之前的写法,可能会导致cmp函数没有返回值, 152 先填A串再填B串,然后都是B串的话就没法比较了吧。不知道。挺懵逼的 153 不是。好像是因为。等长的B串之间,比较的话,都是B>=B然后一直swap? 154 */ 155 int lstb=0; 156 for(int j=0;j<V[i].size();j++){ 157 //printf("%d %d %d\n",V[i][j].len,V[i][j].isa,V[i][j].num); 158 if(V[i][j].isa){ 159 add(In(i),V[i][j].num,V[i][j].len);//in -> A 160 if(lstb)add(lstb,V[i][j].num,V[i][j].len);//B -> A 161 } 162 else { 163 if(lstb)add(lstb,V[i][j].num,0); 164 lstb=V[i][j].num; 165 } 166 } 167 if(lstb)add(lstb,Out(i),0); 168 } 169 scanf("%d",&m); 170 for(int i=1,x,y;i<=m;i++){ 171 scanf("%d%d",&x,&y); 172 add(ga[x],gb[y],0); 173 } 174 topological_sort(); 175 clear(); 176 } 177 return 0; 178 }
查错好方法:不断提交,屏蔽除输入输出之外的所有code。
问题分析(fp):
一开始很多bug:数组越界,没有清空之类。
终极bug(快2h):sort内部如何实现?如果两个东西来回比较的大小都是一样的,会怎样?