码迷,mamicode.com
首页 > 其他好文 > 详细

字符串相关模板

时间:2018-01-20 17:54:41      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:[1]   zoj   习题   后缀数组   linked   lib   相关   stdin   name   

KMP、AC自动机、后缀数组、后缀自动机、manacher、回文自动机

KMP

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int len1,len2,nt[maxn];
char s[maxn],c[maxn];

int main() {
    scanf("%s%s",s+1,c+1);
    len1=strlen(s+1);s[len1+1]=‘#‘;
    len2=strlen(c+1);c[len2+1]=‘#‘;
    int pos;
    for(int i=2;i<=len2;++i) {
        pos=nt[i-1];
        while(pos&&c[pos+1]!=c[i]) pos=nt[pos];
        nt[i]= c[pos+1]==c[i]? pos+1:0;
    }
    pos=0;
    for(int i=1;i<=len1;++i) {
        while(pos&&c[pos+1]!=s[i]) pos=nt[pos];
        if(c[pos+1]==s[i]) pos++;
        if(pos==len2) printf("%d\n",i-len2+1),pos=nt[pos];
    }
    for(int i=1;i<=len2;++i) printf("%d ",nt[i]); 
    return 0;
}

  

AC自动机(bzoj3530)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=1500+7; 
const ll mod=1e9+7;
int n,m;
char s[maxn],d[maxn];
 
char cc;ll ff;
template<typename T>void read(T& aa) {
    aa=0;ff=1; cc=getchar();
    while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar();
    if(cc==‘-‘) ff=-1,cc=getchar();
    while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
    aa*=ff;
}
 
void mo(ll &x){if(x>=mod) x-=mod;}
 
int fail[maxn],son[maxn][11],has[maxn],tot;
void insert() {
    int len=strlen(s+1),now=0,x;
    for(int i=1;i<=len;++i) {
        x=s[i]-‘0‘;
        if(!son[now][x]) son[now][x]=++tot;
        now=son[now][x];
    }
    has[now]=1;
}
 
int zz[maxn];
void bld() {
    int s=1,t=0,x;
    for(int i=0;i<10;++i) if(son[0][i]) zz[++t]=son[0][i];
    while(s<=t) {
        x=zz[s++]; has[x]|=has[fail[x]];
        for(int i=0;i<10;++i) {
            if(son[x][i]) {
                fail[son[x][i]]=son[fail[x]][i];
                zz[++t]=son[x][i];
            }
            else son[x][i]=son[fail[x]][i];
        }
    }
}
 
ll f[maxn][maxn][4];
ll solve(int pos,int len,int p) {
    if(has[pos]) return 0;
    if(len>n) return 1;
    if(~f[pos][len][p]) return f[pos][len][p];
    ll rs=0;
    if(p&2) rs+=solve(pos,len+1,p&2);
    int l=p>>1,r=(p&1)? (d[len]-‘0‘):9;
    for(int i=l;i<=r;++i) {
        rs+=solve(son[pos][i],len+1,(p&1)&(i==d[len]-‘0‘));
        mo(rs);
    } 
    return f[pos][len][p]=rs;
}
 
int main() {
    scanf("%s",d+1); n=strlen(d+1);
    read(m);
    for(int i=1;i<=m;++i) {
        scanf("%s",s+1);
        insert();
    }
    bld();
    memset(f,-1,sizeof(f));
    printf("%lld",(solve(0,1,3)-1+mod)%mod);
    return 0;
}
/*
20
3
2
3
14
*/

  

后缀数组、manacher(0103练习题T3,和去年省选D2T3很像,但不用本质不同,而且简单很多,用后缀数组和马拉车预处理lcp和以i为开头的回文串(放到树状数组里))

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
const int maxn=16e5+10,INF=0x3f3f3f3f;
int n,m,Q,ql,qr;ll totans;
char A[maxn],B[maxn],S[2*maxn];
int x[maxn],y[maxn],c[maxn],sa[maxn],h[maxn],rad[maxn];

ll aa;char cc;
ll read() {
	aa=0;cc=getchar();
	while(cc<‘0‘||cc>‘9‘) cc=getchar();
	while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
	return aa;
}

ll minnum[4*maxn];
void bld(int pos,int l,int r) {
	if(l==r) {
		minnum[pos]=h[l];
		return;
	}
	int mid=(l+r)>>1;
	bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r);
	minnum[pos]=min(minnum[pos<<1],minnum[pos<<1|1]);
}

ll qmin(int pos,int l,int r) {
	if(l>=ql&&r<=qr) return minnum[pos];
	int mid=(l+r)>>1;ll rs=INF;
	if(ql<=mid) rs=min(rs,qmin(pos<<1,l,mid));
	if(qr>mid) rs=min(rs,qmin(pos<<1|1,mid+1,r));
	return rs;
}

ll tot[2][maxn],sum[2][maxn];
ll q(int pos,ll *sz) {
	ll rs=0;
	while(pos) {
		rs+=sz[pos];
		pos-=pos&-pos;
	}
	return rs;
}

void chge(int pos,int x,ll *sz,int n) {
	while(pos<=n) {
		sz[pos]+=x;
		pos+=pos&-pos;
	}
}

void get_sa(char *s,int n) {
	int m=‘z‘+1,p;
	for(int i=0;i<n;++i) c[x[i]=s[i]]++;
	for(int i=1;i<m;++i) c[i]+=c[i-1];
	for(int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
	for(int k=1;k<=n;k<<=1) {
		p=0;
		for(int i=n-1;i>=n-k;--i) y[p++]=i;
		for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
		for(int i=0;i<m;++i) c[i]=0;
		for(int i=0;i<n;++i) c[x[y[i]]]++;
		for(int i=1;i<m;++i) c[i]+=c[i-1];
		for(int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
		
		swap(x,y);p=1;
		x[sa[0]]=0;
		for(int i=1;i<n;++i) 
			x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&
			((sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k])||(sa[i]+k>=n&&sa[i-1]+k>=n))? p-1:p++;
		if(p>=n) break; else m=p;
	}
	p=0;int u;
	for(int i=0;i<n;++i) {
		if(!x[i]) continue;
		u=sa[x[i]-1];
		if(p) p--;
		while(s[u+p]==s[i+p]) p++;
		h[x[i]]=p;
	}
	memset(minnum,0x3f3f3f3f,sizeof(minnum));
	bld(1,1,n-1);
}

void manacher(char *s,ll *sz,int len,int o) {
	int maxpos=0,p=0;
	for(int i=len;i;--i) {//不是从0开始而是从1开始 
		s[i<<1]=s[i];
		s[i<<1|1]=‘#‘;
	}
	s[0]=s[1]=‘#‘;
	for(int i=2;i<=2*len;++i) {
		if(maxpos>i) rad[i]=min(maxpos-i,rad[2*p-i]);
		else rad[i]=0;
		while(i-rad[i]>0&&i+rad[i]<=2*len+1&&s[i-rad[i]]==s[i+rad[i]]) rad[i]++;
		rad[i]--;
		if(i+rad[i]>maxpos) p=i,maxpos=i+rad[i];
	}
	for(int i=2;i<=2*len;++i) {
		chge((i-rad[i]+1)>>1,1,tot[o],len);
		chge((i+2)>>1,-1,tot[o],len);
	}
}

int main() {
	freopen("palindrome.in","r",stdin);
	freopen("palindrome.out","w",stdout);
	scanf("%s",A+1);
	scanf("%s%s",A+1,B+1);
	n=strlen(A+1); m=strlen(B+1);
	for(int i=1;i<=m/2;++i) swap(B[i],B[m-i+1]);
	for(int i=1;i<=n;++i) S[i-1]=A[i]; S[n]=‘#‘;//n不是n+1 
	for(int i=1;i<=m;++i) S[i+n]=B[i];
	get_sa(S,n+m+1);
	manacher(A,tot[0],n,0);
	manacher(B,tot[1],m,1);
	for(int i=1;i<=n;++i) chge(i,q(i,tot[0]),sum[0],n+1); 
	for(int i=1;i<=m;++i) chge(i,q(i,tot[1]),sum[1],m+1);
	//注意是n+1和m+1,因为可能询问到 
	
	Q=read();int xx,yy,len;
	for(int i=1;i<=Q;++i) {
		xx=read(); yy=read();
		ql=x[xx-1]; qr=x[yy+n];
		if(qr<ql) swap(ql,qr);
		++ql;
		len=qmin(1,1,n+m);
		totans=len;
		totans+=q(xx+len,sum[0])-q(xx,sum[0]);
		totans+=q(yy+len,sum[1])-q(yy,sum[1]);//注意边界 
		printf("%lld\n",totans);
	}
	fclose(stdin);fclose(stdout);
	return 0;
}
/*
orzAchen
babaabbba
baaabbb
1
9 6
*/ 

  

后缀自动机(bzoj2555 LCT+SAM)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define lc son[pos][0]
#define rc son[pos][1]
const int maxn=1200000+7;
int mask,n,m,ans;
char s[maxn];
string chars;
 
char cc;ll ff;
template<typename T>void read(T& aa) {
    aa=0;ff=1; cc=getchar();
    while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar();
    if(cc==‘-‘) ff=-1,cc=getchar();
    while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar();
    aa*=ff;
}
 
void gets(int mask)
{
    scanf("%s",s);
    chars=s; int len=chars.length();
    for(int j=0;j<len;j++) 
    {
        mask=(mask*131+j)%len;
        char t=chars[j];
        chars[j]=chars[mask];
        chars[mask]=t;
    }
}
 
struct Lct{
    int fa[maxn],son[maxn][2],w[maxn],laz[maxn],zz[maxn],t;
    void pd(int pos) {
        if(!laz[pos]) return;
        if(lc) laz[lc]+=laz[pos],w[lc]+=laz[pos];
        if(rc) laz[rc]+=laz[pos],w[rc]+=laz[pos];
        laz[pos]=0;
    }
    bool isroot(int pos) {
        return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos;
    }
    void rotate(int pos) {
        int x,y,p,t; y=fa[x=fa[pos]];t=isroot(x);
        p=son[x][1]==pos;
        son[x][p]=son[pos][!p];  fa[son[pos][!p]]=x;
        son[pos][!p]=x;          fa[x]=pos;
        fa[pos]=y;
        if(!t) son[y][son[y][1]==x]=pos;
    }
    void splay(int pos) {
        t=0; int x,y;
        for(x=pos;!isroot(x);x=fa[x]) zz[++t]=x;
        zz[++t]=x;
        while(t) pd(zz[t--]);
        for(;!isroot(pos);rotate(pos)) {
            y=fa[x=fa[pos]];
            if(!isroot(x)) 
                (son[x][1]==pos)^(son[y][1]==x)? rotate(pos):rotate(x);
        }
    }
    void access(int pos) {
        for(int t=0;pos;pos=fa[pos]) {
            splay(pos);rc=t;
            t=pos;
        }
    }
    void lk(int x,int f) {
        fa[x]=f; access(f); splay(f); 
        if(f) laz[f]+=w[x],w[f]+=w[x];
    }
    void cut(int pos) {
        access(pos);splay(pos);
        if(lc) laz[lc]-=w[pos],w[lc]-=w[pos];
        fa[lc]=0; lc=0;
    }
}lct;
 
struct Sam{
    Sam* next[27],*par;
    int step; 
}pool[2*maxn],*root,*last;
int tot;
 
Sam* newnode(int step) {
    Sam *t=pool+(tot++);
    t->step=step;
    t->par=NULL;
    memset(t->next,0,sizeof(t->next));
    return t;
}
 
void Extend(int w) {
//  cout<<"Extend"<<w<<": ";
    Sam *p=last;
    Sam *np=newnode(p->step+1);lct.w[tot]=1;
    int x,y;
    for(;p&&!p->next[w];p=p->par) p->next[w]=np;
    if(!p) {
        np->par=root;
//      cout<<"np link->root\n";
        lct.lk(tot,1);
    }
    else {
        Sam *q=p->next[w];x=q-pool+1;
        if(q->step==p->step+1) {
            np->par=q;
//          cout<<"np link->q\n";
            lct.lk(tot,x);
        }
        else {
            Sam *nq=newnode(p->step+1);lct.w[tot]=0;
            memcpy(nq->next,q->next,sizeof(q->next));
            y=q->par-pool+1;
            lct.cut(x);
            nq->par=q->par;
            q->par=nq; lct.lk(x,tot);
            np->par=nq;lct.lk(tot-1,tot);
            lct.lk(tot,y);
//          cout<<"nq linked by q&np\n";
            for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq;
        }
    }
    last=np;
}
 
void add() {
    gets(mask);
    int len=chars.length();
    for(int i=0;i<len;i++) 
        Extend(chars[i]-‘A‘);
}
 
int q(){
    gets(mask);int x;
    int len=chars.length();Sam *now=root;
    for(int i=0;i<len;i++)
        if(!(now=now->next[chars[i]-‘A‘])) return 0;
    lct.splay(x=now-pool+1);
    return lct.w[x];
}
 
int main() {
    read(m);
    scanf("%s",s+1);
    n=strlen(s+1);
    last=root=newnode(0);
    for(int i=1;i<=n;++i) Extend(s[i]-‘A‘);
    for(int i=1;i<=m;++i) {
        scanf("%s",s);
        if(s[0]==‘A‘) add();
        else {
            ans=q();
            printf("%d\n",ans);
            mask^=ans;
        }
    }
    return 0;
}
/*
4
A
ADD BBABBBBAAB
QUERY ABA
ADD BBABAB
QUERY BAAB
*/

  

回文自动机留坑

 

字符串相关模板

标签:[1]   zoj   习题   后缀数组   linked   lib   相关   stdin   name   

原文地址:https://www.cnblogs.com/Serene-shixinyi/p/8321281.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!