模板复习计划——字符串

来源:互联网 发布:手机淘宝 二手 编辑:程序博客网 时间:2024/04/28 00:36

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;}




0 0
原创粉丝点击