一些字符串的题
1.BZOJ 2434 阿狸的打字机
AC自动机+树状数组
//Twenty
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100000+29;
char s[maxn];
int tot,n,m,ecnt,fi[maxn],nx[maxn],tt[maxn],fir[maxn],nxt[maxn],to[maxn];
int ls[maxn],le[maxn],dfs_clock,sum[maxn],cnt,num[maxn],ans[maxn],xbh[maxn];
int qry(int x){
int res=0;
for(int i=x;i>0;i-=(i&(-i)))
res+=sum[i];
return res;
}
void addsum(int x,int v){
for(int i=x;i<=tot;i+=(i&(-i)))
sum[i]+=v;
}
struct Node{
int l,r,id,bh;
}qs[maxn];
struct node{
node *s[26],*fail,*fa;
int id,bh;
node(){
for(int i=0;i<26;i++) s[i]=NULL; fail=NULL; fa=NULL;
}
}*root,*now,*tep;
void add(int u,int v,int k){
nx[++ecnt]=fi[u];fi[u]=ecnt;tt[ecnt]=v; num[ecnt]=k;
}
void add_edge(int u,int v){
nxt[++cnt]=fir[u]; fir[u]=cnt; to[cnt]=v;
}
void build(){
root=new node();
root->bh=++tot;
now=root;
for(int i=0;s[i]!='\0';i++){
if(s[i]=='P') {now->id=++n; xbh[n]=tot; }
else if(s[i]=='B') now=now->fa ;
else{
int c=s[i]-'a';
if(now->s[c]==NULL){
tep=new node();
tep->bh=++tot;
now->s[c]=tep;
now->s[c]->fa=now;
}
now=now->s[c];
}
}
}
void dfs(int x){
ls[x]=++dfs_clock;
for(int i=fir[x];i;i=nxt[i]){
dfs(to[i]);
}
le[x]=dfs_clock;
}
int query(int x){
return qry(le[x])-qry(ls[x]-1);
}
void get_fail(){
queue<node*>que;
que.push(root);
while(!que.empty() ){
now=que.front(); que.pop();
for(int i=0;i<26;i++)
if(now->s[i]!=NULL){
if(now==root) now->s[i]->fail=root;
else{
tep=now->fail;
while(tep->s[i]==NULL&&tep->fail!=NULL) tep=tep->fail;
if(tep->s[i]) now->s[i]->fail =tep->s[i];
else now->s[i]->fail=root;
}
add_edge(now->s[i]->fail->bh,now->s[i]->bh);
que.push(now->s[i]);
}
}
}
void travel(){
now=root;
for(int i=0;s[i]!='\0';i++){
if(s[i]=='P') {
if(fi[now->id]){
for(int j=fi[now->id];j;j=nx[j]){
ans[num[j]]=query(xbh[tt[j]]);
}
}
}
else if(s[i]=='B') {addsum(ls[now->bh],-1); now=now->fa ;}
else{
int c=s[i]-'a';
now=now->s[c];
addsum(ls[now->bh],1);
}
}
}
int main(){
scanf("%s",s);
build();
get_fail();
dfs(1);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&qs[i].l,&qs[i].r);
add(qs[i].r,qs[i].l,i); qs[i].id=i;
}
travel();
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
2.hash UVA 4513口吃的外星人
紫书原题
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=4e5+29;
const int x=123;
char s[maxn];
int pos,m,ans,n,rak[maxn],hs[maxn],xl[maxn],has[maxn];
using namespace std;
bool cmp(const int &a,const int &b){
return has[a]==has[b]?a<b:has[a]<has[b];
}
bool check(int l){
int c=0; pos=-1;
for(int i=0;i<n-l+1;i++){
rak[i]=i;
has[i]=hs[i]-hs[i+l]*xl[l];
}
sort(rak,rak+n-l+1,cmp);
for(int i=0;i<n-l+1;i++){
if(i==0||has[rak[i]]!=has[rak[i-1]]) c=0;
if(++c>=m) pos=max(pos,rak[i]);
}
return pos>-1;
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
while(scanf("%d",&m)){
if(!m) break;
scanf("%s",s);
n=strlen(s);
hs[n]=0;
for(int i=n-1;i>=0;i--)
hs[i]=hs[i+1]*x+(s[i]-'a');
xl[0]=1;
for(int i=1;i<=n;i++) xl[i]=xl[i-1]*x;
if(!check(1)) printf("none\n");
else{
int l=1,r=n+1;
while(r-l>1){
int mid=l+((r-l)>>1);
if(check(mid)) l=mid;
else r=mid;
}
check(l);
printf("%d %d\n",l,pos);
}
}
return 0;
}
3.BZOJ 2342 双倍回文
manacher 没想开 手写了一颗treap
BZOJ 2342 双倍回文
4.BZOJ 3230 相似子串
后缀数组
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100000+50;
typedef long long LL; //LL真的害死人啊
int m=150,n,Q,saz[maxn],saf[maxn],rakz[maxn],rakf[maxn];
int hz[maxn],hf[maxn],stz[maxn][20],stf[maxn][20];
char ch[maxn],sz[maxn*2],sf[maxn*2];
LL sum[maxn];
inline bool mp(int *y,int p,int q,int k){
int o0=p+k>=n?-1:y[p+k];
int o1=q+k>=n?-1:y[q+k];
return o0==o1&&y[p]==y[q];
}
void make_hight(char *s,int *hight,int *sa,int st[][20],int *rank){
for(int i=0;i<n;i++) rank[sa[i]]=i;
int k=0;
for(int i=0;i<n;i++){
//st[i][0]=n-sa[i]; //st[i][j]表示i到i+2^j而不能是i到i+2^j-1 否则。。
if(!rank[i]) continue;
if(k) k--;
int j=sa[rank[i]-1];
while(s[j+k]==s[i+k]) k++;
hight[rank[i]]=k;
st[rank[i]-1][0]=k;
}
for(int j=1;j<=20;j++)
for(int i=0;i+(1<<j)<n;i++)
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
void make_sa(char *s,int *sa,int st[][20],int *rank,int *hight){
static int t1[maxn],t2[maxn],c[maxn];
int i,*x=t1,*y=t2;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(int k=1;k<=n;k<<=1){
int p=0;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=mp(y,sa[i],sa[i-1],k)?p-1:p++;
if(p>=n) break;
m=p;
}
make_hight(s,hight,sa,st,rank);
}
void make_sum(){
sum[0]=n-saz[0];
for(int i=1;i<n;i++)
sum[i]=sum[i-1]+n-saz[i]-hz[i];
}
int ef(LL x,int &rel,int &rer){
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(sum[mid-1]>=x) rel=mid-1,r=mid-1;
else l=mid+1;
}
rer=n-(sum[rel]-x)-1;
rel=saz[rel];
}
LL RMQ(int st[][20],int *sa,int l,int r){
int k=0;
if(l==r) return n-sa[l];
while(l+(1<<k)<=r) k++;
if(k) k--;
return (LL)min(st[l][k],st[r-(1<<k)][k]);
}
LL qry(LL l,LL r){
int l1,r1,l2,r2;
ef(l,l1,r1);
ef(r,l2,r2);
LL ans1=(LL)min(r1-l1+1,r2-l2+1);
LL ans2=(LL)min(r1-l1+1,r2-l2+1);
l1=rakz[l1]; l2=rakz[l2];
if(l1>l2) swap(l1,l2);
ans1=min(ans1,RMQ(stz,saz,l1,l2));
r1=rakf[n-r1-1]; r2=rakf[n-r2-1];
if(r1>r2) swap(r1,r2);
ans2=min(ans2,RMQ(stf,saf,r1,r2));
return ans1*ans1+ans2*ans2;
}
int main()
{
scanf("%d%d",&n,&Q);
scanf("%s",sz);
for(int i=0;i<n;i++) sf[i]=sz[n-i-1];
make_sa(sz,saz,stz,rakz,hz);
make_sa(sf,saf,stf,rakf,hf);
make_sum();
while(Q--){
LL ql,qr;
scanf("%lld%lld",&ql,&qr);
if(ql>sum[n-1]||qr>sum[n-1]) printf("-1\n");
else printf("%lld\n",qry(ql,qr));
}
return 0;
}
5.BZOJ 3238 差异
后缀数组 单调栈优化
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<stack>
const int maxn=100000+5;
typedef long long LL;
char s[maxn];
int mi=1e9+7,m=150,n,sa[maxn],hight[maxn],rank[maxn],l[maxn],r[maxn];
using namespace std;
void make_hight(){
for(int i=0;i<n;i++) rank[sa[i]]=i;
int k=0;
for(int i=0;i<n;i++){
if(!rank[i]) continue;
if(k) k--;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
hight[rank[i]]=k;
}
}
bool mp(int *y,int a,int b,int k){
int o1=(a+k)>=n?-1:y[a+k];
int o2=(b+k)>=n?-1:y[b+k];
return (o1==o2&&y[a]==y[b]);
}
void make_sa(){
static int t1[maxn],t2[maxn],c[maxn];
int *x=t1,*y=t2,i,k;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[i]=s[i]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(k=1;k<=n;k<<=1){
int p=0;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=1;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y); p=1; x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=mp(y,sa[i],sa[i-1],k)?p-1:p++;
if(p>=n) break;
m=p;
}
make_hight();
}
LL work(){
LL ans=0,res=0;
int now;
for(int i=n;i>=1;i--){
ans+=(LL)i*(LL)(n-1);
}
stack<int>que; que.push(0);
for(int i=1;i<n;i++){
while(!que.empty()&&(hight[now=que.top()]>hight[i])){
que.pop();
}
if(!que.empty()){
now=que.top();
l[i]=now;
}
else l[i]=-1;
que.push(i);
}
while(!que.empty()) que.pop();
for(int i=n-1;i>0;i--){
while(!que.empty()&&(hight[now=que.top()]>=hight[i])){
que.pop();
}
if(!que.empty()){
now=que.top();
r[i]=now;
}
else r[i]=n;
que.push(i);
}
for(int i=0;i<n;i++)
res+=(LL)(i-l[i])*(r[i]-i)*hight[i];
return ans-res*2;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%s",s);
n=strlen(s); //m=n;
//for(int i=0;i<n;i++) {int smg=s[i]; mi=min(mi,smg);}
make_sa();
printf("%lld\n",work());
return 0;
}