模板复习计划——字符串

http://uoj.ac/problem/35 后缀数组 模板来自千古神犇jxr,宏改进版

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=1;i--)
#define equ(x) (y[sa[i]+x]==y[sa[i-1]+x])
const int N=100000+5;
int a[N],b[N],c[N],*x,*y,sa[N],rk[N],h[N],n;
char s[N];
void radix(int m){
	rep(i,1,m)c[i]=0;
	rep(i,1,n)c[x[y[i]]]++;
	rep(i,1,m)c[i]+=c[i-1];
	per(i,n,1)sa[c[x[y[i]]]--]=y[i];
}
void build(int m){
	rep(i,1,n)x[i]=s[i],y[i]=i;radix(m);
	for(int k=1,p=0;k<=n;k<<=1,m=p,p=0){
		rep(i,n-k+1,n)y[++p]=i;
		rep(i,1,n)if(sa[i]>k)y[++p]=sa[i]-k;
		radix(m);swap(x,y);x[sa[1]]=p=1;
		rep(i,2,n)x[sa[i]]=equ(0)&&equ(k)?p:++p;
		if(p==n)break;
	}
	rep(i,1,n)rk[sa[i]]=i;
	for(int i=1,k=0;i<=n;h[rk[i++]]=k)
	for(k?k--:0;i+k<=n&&s[i+k]==s[sa[rk[i]-1]+k];k++);
}
int main(){
	//freopen("a.in","r",stdin);
	scanf("%s",s+1);n=strlen(s+1);
	x=a;y=b;build(200);
	rep(i,1,n)printf("%d ",sa[i]);putchar('\n');
	rep(i,2,n)printf("%d ",h[i]);putchar('\n');
	return 0;
}

http://codevs.cn/problem/1204/ KMP( 感觉这个好像不用复习吧……)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;i++)
const int N=100+5;
char s[N],t[N];
int n,m,fail[N];
void getfail(){
	int j=0;
	rep(i,2,m){
		while(j&&t[j+1]!=t[i])j=fail[j];
		j+=t[j+1]==t[i];
		fail[i]=j;
	}
}
int kmp(){
	int j=0;
	rep(i,1,n){
		while(j&&t[j+1]!=s[i])j=fail[j];
		j+=t[j+1]==s[i];
		if(j==m)return i-m+1;
	}
}
int main(){
	//freopen("a.in","r",stdin);
	scanf("%s%s",s+1,t+1);n=strlen(s+1);m=strlen(t+1);
	getfail();printf("%d\n",kmp());
	return 0;
}


http://acm.hdu.edu.cn/showproblem.php?pid=3068 manacher( 话说我会回文树还要这个干嘛)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=110000+5;
const int M=220000+5;
#define rep(i,l,r) for(int i=l;i<=r;i++)
char s[N],t[M];
int n,m,p[M];
void build(){
	for(int i=1;i<=n;i++)
	t[i<<1]=s[i],t[i*2-1]='#';
	t[m=2*n+1]='#';
}
void manacher(){
	int mx=0,id=0;
	rep(i,1,m){
		if(mx>i)p[i]=min(p[2*id-i],mx-i);
		else p[i]=1;
		while(i-p[i]>=1&&i+p[i]<=m&&t[i-p[i]]==t[i+p[i]])p[i]++;
		if(i+p[i]>mx)mx=i+p[i],id=i;
	}
}
int main(){
	//freopen("a.in","r",stdin);
	while(~scanf("%s",s+1)){
		n=strlen(s+1);
		build();
		manacher();
		int ans=0;
		rep(i,1,m)ans=max(ans,p[i]);
		printf("%d\n",ans-1);
	}
	return 0;
}


http://uoj.ac/problem/103 回文树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
typedef long long ll;
const int N=300000+5;
int len[N],suf[N],ch[N][26],sum[N];
int node,last;
void init(){
	len[suf[suf[2]=1]=1]=-1;
	node=last=2;
}
char s[N];
bool add(int i){
	int cur=last,c=s[i]-'a';
	while(s[i-len[cur]-1]!=s[i])cur=suf[cur];
	bool flag=true;
	if(!ch[cur][c]){
		len[last=++node]=len[cur]+2;ch[cur][c]=last;
		int tmp=suf[cur];
		while(s[i-len[tmp]-1]!=s[i])tmp=suf[tmp];
		suf[last]=len[last]==1?2:ch[tmp][c];
	}else flag=false;
	last=ch[cur][c];sum[last]++;
	return flag;
}
int main(){
	//freopen("a.in","r",stdin);
	scanf("%s",s+1);int n=strlen(s+1);
	init();
	rep(i,1,n)add(i);
	per(i,node,1)sum[suf[i]]+=sum[i];
	ll ans=0;
	rep(i,1,node)ans=max(ans,(ll)len[i]*sum[i]);
	printf("%lld\n",ans);
	return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=4622 后缀自动机( 默念十遍……后缀自动机要开两倍空间)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=2000+5;
struct state{
	state *par,*go[26];
	int len;
	void clear(){
		par=0;len=0;
		memset(go,0,sizeof(go));
	}
	int calc(){
		if(!par)return 0;
		return len-par->len;
	}
}statepool[N<<1],*cur,*root,*last;
void init(){
	cur=statepool;
	last=root=cur++;
	root->clear();
}
int extend(int w){
	int ans=0;
	state *p=last,*np=cur++;
	np->clear();np->len=p->len+1;
	for(;p&&!p->go[w];p=p->par)p->go[w]=np;
	if(!p)np->par=root;
	else{
		state *q=p->go[w];
		if(q->len==p->len+1)np->par=q;
		else{
			state *nq=cur++;nq->clear();
			memcpy(nq->go,q->go,sizeof(q->go));
			nq->len=p->len+1;
			ans-=q->calc();
			nq->par=q->par;
			q->par=np->par=nq;
			ans+=q->calc()+nq->calc();
			for(;p&&p->go[w]==q;p=p->par)p->go[w]=nq;
		}
	}
	ans+=np->calc();
	last=np;
	return ans;
}
char s[N];
int table[N][N];
int main(){
	//freopen("a.in","r",stdin);
	int T;scanf("%d",&T);
	while(T--){
		scanf("%s",s+1);int n=strlen(s+1);
		for(int i=1;i<=n;i++){
			init();
			for(int j=i;j<=n;j++)
			table[i][j]=table[i][j-1]+extend(s[j]-'a');
		}
		int q;scanf("%d",&q);
		while(q--){
			int l,r;scanf("%d%d",&l,&r);
			printf("%d\n",table[l][r]);
		}
	}
	return 0;
}


http://acm.hdu.edu.cn/showproblem.php?pid=2222  这也用复习系列之AC自动机(题目有坑)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct Node{
	int fail,ch[26],cnt;
	void clear(){
		memset(ch,0,sizeof(ch));
		fail=cnt=0;
	}
}tr[500005];
int sz;
void init(){
	tr[sz=0].clear();
}
void insert(char *s,int k){
	int u;
	for(u=0;*s;s++){
		int c=*s-'a';
		if(!tr[u].ch[c]){
			tr[u].ch[c]=++sz;
			tr[sz].clear();
		}
		u=tr[u].ch[c];
	}
	tr[u].cnt++;
}
bool ex[10005];
void bfs(){
	queue<int>q;q.push(0);
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=0;i<26;i++)
		if(tr[u].ch[i]){
			int v=tr[u].ch[i];
			if(u)tr[v].fail=tr[tr[u].fail].ch[i];
			q.push(v);
		}else tr[u].ch[i]=tr[tr[u].fail].ch[i];
	}
}
int find(char *s){
	int ans=0;
	for(int u=0;*s;s++){
		int c=*s-'a';
		u=tr[u].ch[c];
		for(int p=u;p;p=tr[p].fail)
		if(tr[p].cnt>=0)ans+=tr[p].cnt,tr[p].cnt=-1;
		else break;
	}
	return ans;
}
char s[55],t[1000005];
int main(){
	//freopen("a.in","r",stdin);
	int T;scanf("%d",&T);
	while(T--){
		int n;scanf("%d",&n);
		init();
		for(int i=1;i<=n;i++){
			scanf("%s",s);
			insert(s,i);
			ex[i]=0;
		}
		bfs();
		scanf("%s",t);
		printf("%d\n",find(t));
	}
	return 0;
}




你可能感兴趣的:(模板复习计划——字符串)