Codeforces 666E Forensic Examination
10696 단어 CodeForces문자열데이터 구조
제목 대의: 원래 문자 S S, m 개의 일치 하 는 문자열 이 있 습 니 다. S [pl, pr] S [p l, p r] 라 는 문 자 는 [l, r] [l, r] 사이 에 있 는 문자열 중 가장 많은 횟수 가 있 는 것 이 무엇 이 냐 고 물 었 습 니 다. 몇 번 이나 나 타 났 습 니까? (최대 횟수 가 같 으 면 출력 번호 가 작은 것)
불완전 이해 + 해법 (접미사 자동 동기 + 선분 트 리 통합)
코드 에 이해
큰 문자열 의 일치 에 대해 우 리 는 S S 와 m 개의 문자열 을 연결 하 는 것 을 선택 한 후에 일치 하 는 문자열 이 right r i g h t 집합 에 나타 나 는 것 을 발견 할 수 있 습 니 다. 그래서 우 리 는 parent p a r e n t 트 리 를 추출 합 니 다.parent p a r e n t 에 대응 하 는 것 은 right r i g h t 집합 트 리 이기 때문에 parent p a r e n t 트 리 에 있 는 점 을 모두 해당 하 는 번 호 를 표시 하고 지속 가능 한 선분 트 리 로 기록 합 니 다.
:
( )
그리고 parent p a r n t 트 리 의 대응 관 계 를 합 쳐 코드 설명 을 구체 적 으로 보 세 요.
코드 + 주석 (코드 는 본인 이 쓴 것 이 아 닙 니 다. 아직 완전히 이해 하지 못 했 기 때 문 입 니 다)
#include
#define ll long long
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int M=24000005;
const int mxn=1200005;
char s[mxn];
int a,b,c,d,num,size,ans;
int cnt,m,T,p,q,np,nq,Q,tot,len;
int ls[M],rs[M],mx[M],id[M],B[mxn],C[mxn];
int color[mxn],pos[mxn],step[mxn],pre[mxn][24],son[mxn][28],root[mxn];
inline void update(int x)//
{
if(mx[ls[x]]==mx[x] && id[ls[x]]<id[x]) id[x]=id[ls[x]];
if(mx[ls[x]]>mx[x]) mx[x]=mx[ls[x]],id[x]=id[ls[x]];
if(mx[rs[x]]>mx[x]) mx[x]=mx[rs[x]],id[x]=id[rs[x]];
}
inline void insert(int &x,int l,int r,int v)//
{
if(!x) x=(++size);
if(l==r) {mx[x]++,id[x]=l;return;}
int mid=l+r>>1;
if(v<=mid) insert(ls[x],l,mid,v);
else insert(rs[x],mid+1,r,v);
update(x);
}// ( ), ( )
inline void find(int x,int l,int r,int L,int R)//
{
if(!x) return;
if(L<=l && r<=R)
{
if(ansid[x];
else if(ans==mx[x] && num>id[x]) num=id[x];
return;
}
int mid=l+r>>1;
if(R<=mid) find(ls[x],l,mid,L,R);
else if(L>mid) find(rs[x],mid+1,r,L,R);
else find(ls[x],l,mid,L,mid),find(rs[x],mid+1,r,mid+1,R);
}
inline int merge(int x,int y,int l,int r)//
{
if(!x||!y) return x|y;// ,
int z=(++size),mid=l+r>>1;//
if(l==r)
{
mx[z]=mx[x]+mx[y];// ,
id[z]=l;
return z;
}
//
ls[z]=merge(ls[x],ls[y],l,mid);
rs[z]=merge(rs[x],rs[y],mid+1,r);
update(z);
return z;
}
inline void sam(int w)// ,w , 0
{
int i,j,c;
fo(i,1,len+1)
{
p=np;
if(i==len+1) c=27;
else c=s[i]-'a'+1;
step[np=(++tot)]=step[p]+1;
if(!w && i<=len) pos[i]=np;//
if(w && i<=len) insert(root[np],1,cnt,w);//m
while(p && !son[p][c])
son[p][c]=np,p=pre[p][0];// parent , pre[p][0] 1
if(!p) {pre[np][0]=1;continue;}
q=son[p][c];
if(step[q]==step[p]+1)
pre[np][0]=q;
else
{
step[nq=(++tot)]=step[p]+1;
memcpy(son[nq],son[q],sizeof son[q]);
pre[nq][0]=pre[q][0];
pre[q][0]=pre[np][0]=nq;
while(p && son[p][c]==q)
son[p][c]=nq,p=pre[p][0];
}
}
}
inline void init()
{
int i,j;
fo(i,1,tot) B[step[i]]++;
fo(i,1,tot) B[i]+=B[i-1];
fo(i,1,tot) C[B[step[i]]--]=i;
for(i=tot;i>=1;i--)
{
int x=C[i],fa=pre[x][0];// parent
root[fa]=merge(root[fa],root[x],1,cnt);// -> parent
}
fo(j,1,22) fo(i,1,tot) pre[i][j]=pre[pre[i][j-1]][j-1];//parent
}
int main()
{
int i,j;
scanf("%s",s+1);
len=strlen(s+1);
tot=np=1,sam(0);
scanf("%d",&cnt);
fo(i,1,cnt)
{
scanf("%s",s+1);
len=strlen(s+1);
sam(i);
}
init();
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d%d%d",&c,&d,&a,&b);
len=b-a+1,b=pos[b];
for(j=22;j>=0;j--)
if(step[pre[b][j]]>=len)
b=pre[b][j];//
ans=0,num=0,find(root[b],1,cnt,c,d);//
if(!ans) printf("%d %d
",c,0);
else printf("%d %d
",num,ans);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
문제 풀이 보고서 의 CodeForces 91B QueueOtherwise, print the i-th walrus's displeasure: the number of other walruses that stand between him and the furthest fro...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.