牛客网多校3 Sort String(后缀数组DC3)

题目:就是给你一个串,对于第i个位置,你可以把前i个字符放到队尾形成一个新的字符串,问你最后一共有几个字符串

DC3卡过去了hhhh

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
using namespace std;
const int maxn=2000001;
int wa[maxn*3],wb[maxn*3],wv[maxn*3],wss[maxn*3];
int c0(int *r,int a,int b)
{
    return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
}
int c12(int k,int *r,int a,int b)
{
    if(k==2)
        return r[a]<r[b]||(r[a]==r[b]&&c12(1,r,a+1,b+1));
    else return r[a]<r[b]||(r[a]==r[b]&&wv[a+1]<wv[b+1]);
}
void sort(int *r,int *a,int *b,int n,int m)
{
    int i;
    for(i=0;i<n;i++) wv[i]=r[a[i]];
    for(i=0;i<m;i++) wss[i]=0;
    for(i=0;i<n;i++) wss[wv[i]]++;
    for(i=1;i<m;i++)wss[i]+=wss[i-1];
    for(int i=n-1;i>=0;i--)
        b[--wss[wv[i]]]=a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
    int i,j,*rn=r+n;
    int *san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
    r[n]=r[n+1]=0;
    for(i=0;i<n;i++) if(i%3!=0)wa[tbc++]=i;
    sort(r+2,wa,wb,tbc,m);
    sort(r+1,wb,wa,tbc,m);
    sort(r,wa,wb,tbc,m);
    for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
        rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
    if(p<tbc)dc3(rn,san,tbc,p);
    else for(i=0;i<tbc;i++) san[rn[i]]=i;
    for(i=0;i<tbc;i++) if(san[i]<tb)wb[ta++]=san[i]*3;
    if(n%3==1)wb[ta++]=n-1;
    sort(r,wb,wa,ta,m);
    for(i=0;i<tbc;i++)wv[wb[i]=G(san[i])]=i;
    for(i=0,j=0,p=0;i<ta&&j<tbc;p++)
        sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
    for(;i<ta;p++)sa[p]=wa[i++];
    for(;j<tbc;p++)sa[p]=wb[j++];
}
void da(int str[],int sa[],int ra[],int height[],int n,int m)
{
	for(int i=n;i<3*n;i++)
        str[i]=0;
    dc3(str,sa,n+1,m);
	int i,j,k=0;
	for(int i=0;i<=n;i++) ra[sa[i]]=i;

	for(int i=0;i<n;i++)
	{
		if(k) k--;
		int j=sa[ra[i]-1];
		while(str[i+k]==str[j+k])k++;
		height[ra[i]]=k;
	}
}

int m,n,k,t;
int ra[maxn*3],height[maxn*3],str[maxn*3],sa[maxn*3];

char s[maxn];
int book[maxn]={0};
#include<vector>
vector<int>ans[maxn];
int main()
{
    scanf("%s",s);
    n=strlen(s);
    m=n;
    for(int i=0;i<n;i++)
    str[i]=s[i]-'a'+1;
    for(int i=n;i<n*2;i++)
        str[i]=str[i-n];
    n*=2;
    str[n]=0;
    da(str,sa,ra,height,n,30);

    int num=0;
    for(int i=0;i<m;i++)
    if(!book[i])
    {
        ans[++num].push_back(i);
        int k=ra[i];
        while(k-1>=1&&sa[k-1]<=m&&height[k]>=m)
        {
            k--;
            if(sa[k]==m) continue;
            book[sa[k]]=1;
            ans[num].push_back(sa[k]);
        }
        k=ra[i];
        while(k+1<n&&sa[k+1]<=m&&height[k+1]>=m)
        {
            k--;
            if(sa[k]==m) continue;
            book[sa[k]]=1;
            ans[num].push_back(sa[k]);
        }
    }

    printf("%d\n",num);
    for(int i=1;i<=num;i++)
    {
        printf("%d",ans[i].size());
        sort(ans[i].begin(),ans[i].end());
        for(int j=0;j<ans[i].size();j++)
            printf(" %d",ans[i][j]);
        puts("");
    }

	return 0;
}

kmp的算法

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int net[maxn],flag;
void kmp_pre(char x[],int m)
{
    int i,j;
    j=net[0]=-1;
    i=0;
    while(i<m)
    {
        while(j>-1&&x[i]!=x[j])
            j=net[j];
        net[++i]=++j;
    }

    if(m%(m-net[m])==0&&net[m]>0)//找寻环节
        flag=m-net[m];
}
int n;
char s[maxn];
int main()
{
    scanf("%s",s);
    n=strlen(s);
    flag=0;
    kmp_pre(s,n);
    if(flag)
    {
        printf("%d\n",flag);
        int num=n/flag;
        for(int i=0;i<flag;i++)
        {
            printf("%d",num);
            for(int j=i;j<n;j+=flag)
                printf(" %d",j);
            puts("");
        }
    }
    else //否则都不是同一组
    {
        printf("%d\n",n);
        for(int i=0;i<n;i++)
            printf("1 %d\n",i);
    }
    return 0;
}

比赛时过题的hash哈希

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int maxn=2e6+10;
ll p[maxn],ha[maxn];
const ll bas=31;
char s[maxn];
int n;
ll findha(int l,int r)
{
    return ha[r]-ha[l-1]*p[r-l+1];
}
struct node{
    int id;
    ll w;
}ma[maxn];
struct node1{
    int fi;
    vector<int>a;
}ans[maxn];
bool cmp(const node &a,const node &b)
{
    if(a.w==b.w) return a.id<b.id;
    return a.w<b.w;
}
bool cp(const node1 &a,const node1 &b)
{
    return a.fi<b.fi;
}
int main()
{
    scanf("%s",s);
    n=strlen(s);
    for(int i=n;i<n+n;i++)
        s[i]=s[i-n];
    n*=2;
    p[0]=1;
    for(int i=1;i<=n;i++)
    {
        p[i]=p[i-1]*bas;
        ha[i]=(ha[i-1]*bas+s[i-1]-'a'+1);
    }
    int m=n/2;
    for(int i=1;i<=m;i++)
    {
        ll tmp=findha(i,i+m-1);
        ma[i].id=i-1;
        ma[i].w=tmp;
    }
    sort(ma+1,ma+m+1,cmp);
    int num=0;
    for(int i=1;i<=m;i++)
    {
        if(ma[i].w!=ma[i-1].w)
        {
            num++;
            ans[num].fi=ma[i].id;
        }
        else ans[num].a.push_back(ma[i].id);
    }
    sort(ans+1,ans+num+1,cp);
    printf("%d\n",num);
    for(int i=1;i<=num;i++)
    {
        printf("%d",ans[i].a.size()+1);
        printf(" %d",ans[i].fi);
        for(int j=0;j<ans[i].a.size();j++)
            printf(" %d",ans[i].a[j]);
        puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dllpxfire/article/details/81254891
DC3