码迷,mamicode.com
首页 > 编程语言 > 详细

字符串算法模板

时间:2017-09-04 18:58:11      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:ons   algorithm   null   ide   build   后缀   min   ast   name   

1.KMP算法

技术分享
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
int next[100];
char p[1000];
int makenext(char p[],int next[])
{
    int n=strlen(p);
    for(int i=1,k=0;i<=n;i++)
    {
        while(k>0&&p[i]!=p[k])
        k=next[k-1];
        if(p[i]==p[k])
        k++;
        next[i]=k;
    }
}
int kmp(char p[],char t[],int next[])
{
    int n=strlen(p);
    int m=strlen(t);
    makenext(p,next);
    for(int i=0,k=0;i<m;i++)
    {
       while(k>0&&t[i]!=p[k])
       k=next[k-1];
       if(t[i]==p[k])
       k++;
       if(k==n)
       return 1;
    }
}
int main()
{
    
    return 0;
}
KMP

 

2.AC自动机

技术分享
//Twenty
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue> 
using namespace std;
int ans,t,n;
char ch[1000001];
struct node{
    node* fail,*s[26];
    int w;
    node(){
        fail=NULL;w=0;
        for(int i=0;i<26;i++)
        s[i]=NULL;
    }
}*head,*tep,*root;
void build(){
    root=head;
    for(int i=0;ch[i]!=\0;i++){
        if(root->s[ch[i]-a]==NULL){
            tep=new node();
            root->s[ch[i]-a]=tep;
        }
        root=root->s[ch[i]-a];
    }
    root->w ++;
}
queue<node*>que;
void getfail(){
    while(!que.empty()){que.pop();}
    que.push(head);
    while(!que.empty()){
        root=que.front();que.pop();
        for(int i=0;i<26;i++){
            if(root->s[i]!=NULL){
              if(root==head) root->s[i]->fail=head;
              else{
                  tep=root->fail;
                  while(tep){
                      if(tep->s[i]!=NULL){
                          root->s[i]->fail=tep->s[i];
                          break;
                      }
                      tep=tep->fail;
                  }
                  if(!tep) root->s[i]->fail=head;
              }
              que.push(root->s[i]);
            }
        }
    }
}
void query(){
    root=head;
    for(int i=0;ch[i]!=\0;i++){
        int h=ch[i]-a;
        while(root->s[h]==NULL&&root->fail!=NULL)
        root=root->fail ;
        if(root->s[h]!=NULL){
            root=root->s[h];
            tep=root;
            while(tep&&tep->w >0){
                ans+=tep->w;
                tep->w =0;
                tep=tep->fail;
            }
        }
    }
}
int main(){ 
    scanf("%d",&t);
    while(t--){
        head=new node();
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",ch);
            build();
        }
        getfail();
        scanf("%s",ch);
        ans=0;
        query();
        printf("%d\n",ans);
    }
    return 0;
}
AC自动机 指针版
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue> 
#include<vector>
#include<stack>
const int maxn=1e6+29;
using namespace std;
int tot,cs,a,ans,n,an[150];
char s[maxn],ch[200][100];
struct node{
  node *s[26],*fail,*last;
  int w,o,id;
  node(){
    for(int i=0;i<26;i++) s[i]=NULL;
    fail=NULL; w=0; o=0; id=0; last=NULL;
  }
}*root,*tep,*now;
void insert(int x){
    now=root;
    for(int i=0;ch[x][i]!=\0;i++){
       a=ch[x][i]-a;
       if(!now->s[a]){
        tep=new node();
        now->s[a]=tep;
       }
       now=now->s[a];
    }
    now->w++;
    now->id=x;
}
stack<node*>sta;
void get_fail(){
   queue<node*>que;
   que.push(root);
   while(!que.empty() ){
     now=que.front(); que.pop() ; sta.push(now); 
     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->fail&&tep->s[i]==NULL) tep=tep->fail;
          if(tep->s[i]!=NULL) now->s[i]->fail=tep->s[i];
          else now->s[i]->fail=root; 
        }
        que.push(now->s[i]);
      }
   }
}
void query(){ 
   now=root;
   for(int i=0;s[i]!=\0;i++){
        a=s[i]-a;
     while(now->s[a]==NULL&&now->fail!=NULL ) now=now->fail;
     if(now->s[a]!=NULL){
         now=now->s[a];
         now->o++;
     }
   }
}
/*void dfs(node *x){
  for(int i=0;i<26;i++)
   if(x->s[i]!=NULL) dfs(x->s[i]);
   if(x->w>0&&x->o==tot){
    an[++cs]=x->id;
   }
   else if(x->w>0&&x->o>tot){
    cs=0;
    tot=x->o;
    an[++cs]=x->id;
   }
   if(x->fail!=NULL) x->fail->o+=x->o;
}*/  
void cul(){
   while(!sta.empty()){
    node *x=sta.top(); sta.pop();
    for(int i=0;i<26;i++)
    if(x->s[i]!=NULL){
    if(x->s[i]->w>0&&x->s[i]->o==tot){
    an[++cs]=x->s[i]->id;
    }
    else if(x->s[i]->w>0&&x->s[i]->o>tot){
     cs=0;
     tot=x->s[i]->o;
     an[++cs]=x->s[i]->id;
    }
     if(x->s[i]->fail!=NULL) x->s[i]->fail->o+=x->o;
    }
   }
}
int main()
{
   while(scanf("%d",&n)){
   if(n==0) break;
   cs=0;tot=0;
   root=new node();
   for(int i=1;i<=n;i++){
    scanf("%s",ch[i]);
    insert(i);
   }
   get_fail();
   scanf("%s",s);
   query();
   //dfs(root);
   cul();
   sort(an+1,an+cs+1);
   //printf("【\n");
   printf("%d\n",tot);
   for(int i=1;i<=cs;i++) {
   for(int j=0;ch[an[i]][j]!=\0;j++)
   printf("%c",ch[an[i]][j]);
   printf("\n");
   }//printf("】\n");
   }
   return 0;
}
AC自动机 洛谷加强版
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1000000+299;
typedef long long LL;
int m,n,tot,ch[maxn][26],p[maxn],fail[maxn],id[maxn],sum[maxn],dfs_clock;
int fir[maxn],nxt[maxn],to[maxn],root,now,tep,que[maxn],ql=1,qr,xbh[maxn];
int ecnt,le[maxn],ls[maxn],val[maxn];
LL ans;
char s[maxn];
void add_edge(int u,int v){
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
}
void add(int x,int v){
    for(int i=x;i<=tot;i+=(i&(-i))) 
    sum[i]+=v;
}
int qry(int x){
    int res=0;
    for(int i=x;i>=1;i-=(i&(-i))) 
    res+=sum[i];
    return res;
}
void build(int idd){
    now=root;
    for(int i=0;s[i]!=\0;i++){
        int c=s[i]-a;
        if(!ch[now][c]){
            ch[now][c]=++tot;
            p[tot]=now;
        }
        now=ch[now][c];
    }
    id[now]=idd;
    xbh[idd]=now;
}
void get_fail(){
    que[++qr]=root;
    while(ql<=qr){
        now=que[ql++];
        for(int i=0;i<26;i++)
        if(ch[now][i])
        {
            if(now==root) fail[ch[now][i]]=root;
            else{
                tep=fail[now];
                while(!ch[tep][i]&&fail[tep]) tep=fail[tep];
                if(ch[tep][i]) fail[ch[now][i]]=ch[tep][i];
                else fail[ch[now][i]]=root;
            }
            add_edge(fail[ch[now][i]],ch[now][i]);
            que[++qr]=ch[now][i];
        }
    }
}
void dfs(int x,int fa){
    ls[x]=++dfs_clock;
    if(id[x]) val[ls[x]]++;
    val[ls[x]]+=val[ls[fa]];
    add(ls[x],val[ls[x]]-val[dfs_clock-1]);
    for(int i=fir[x];i;i=nxt[i]){
        dfs(to[i],x);
    }
    le[x]=dfs_clock;
}
void change(int x,int f){
    add(ls[x],f); add(le[x]+1,-f); 
}
void travel(){
    now=root;
    for(int i=1;s[i]!=\0;i++){
        int c=s[i]-a;
        while(!ch[now][c]&&fail[now]) now=fail[now];
        if(ch[now][c]){
            now=ch[now][c];
            ans+=qry(ls[now]);
        }
    }
}
int main()
{
    //freopen("c.in","r",stdin);
    //freopen("c.out","w",stdout);
    scanf("%d%d",&m,&n);
    root=++tot;
    for(int i=1;i<=n;i++){
       scanf("%s",s);
       build(i);
    }
    get_fail();
    dfs(root,0);
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        if(s[0]==+){ 
           int x=0;
           for(int i=1;s[i]!=\0;i++) x=x*10+s[i]-0;
           change(xbh[x],1);
        }
        else if(s[0]==-){
           int x=0;
           for(int i=1;s[i]!=\0;i++) 
           x=x*10+s[i]-0;
           change(xbh[x],-1);
        }
        else{
          ans=0;
          travel();
          printf("%lld\n",ans);
        }
    }
    return 0;
}
AC自动机 数组版

 

3.Manacher 

技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=110005;
char s[maxn],ss[maxn*2+50];
int ans,n,nn,rad[maxn*20+50];
void work(){
  ans=0;
  for(int i=1,j=0,k;i<nn;){
    while(ss[i-j-1]==ss[i+j+1]) j++;
    rad[i]=j;
    ans=max(ans,rad[i]);
    for(k=1;k<=j&&rad[i]-k!=rad[i-k];k++) {
      rad[i+k]=min(rad[i]-k,rad[i-k]);
}
    i+=k;
    j=max(j-k,0);
  }
}
int main()
{
   while(~scanf("%s",s)){
     n=strlen(s);
     ss[nn++]=*;
     ss[nn++]=#;
     for(int i=0;i<n;i++){     
       ss[nn++]=s[i];
       ss[nn++]=#;
     }
     ss[nn++]=&;
     work();
     printf("%d\n",ans);
     nn=0;
   }
   return 0;
}
Manacher

 

4.后缀数组

技术分享
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=400050;
char s[maxn];
int n,m=124,n1,sa[maxn],rank[maxn],h[maxn];
int fa[maxn],st[maxn],en[maxn],q[maxn];
typedef long long ll;
ll ans;
using namespace std;
void read(int &cnt){
    char ch=getchar();
    while(ch>z||ch<a) ch=getchar();
    for(;ch>=a&&ch<=z;ch=getchar()) s[cnt++]=ch;
}
void make_hight(const char *s,int n){
    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[j+k]==s[i+k]) k++;
        h[rank[i]]=k;
    }
}
bool cmp(const int &a,const int &b){
    return h[a]>h[b];
}
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_sa(const char *s,int n){
    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,n);
}
int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
int main()
{
   /*read(n1);n=n1;s[n++]=‘{‘;*/read(n);
   make_sa(s,n);
   for(int i=0;i<n;i++){
    fa[i]=i;q[i]=i;
    if(sa[i]>n1) en[i]=1;
    else if(sa[i]<n1) st[i]=1; 
   }
   sort(q,q+n,cmp);
   for(int i=0;i<n;i++){
     if(!q[i]) continue;
        int x=find(q[i]), y=find(q[i]-1);
        ans+=ll(st[x]*en[y]+st[y]*en[x])*(ll)h[q[i]];
        st[x]+=st[y];en[x]+=en[y];fa[y]=x;
   }
   printf("%lld\n",ans);
   return 0;
}
后缀数组

 

5.后缀自动机

技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=2000005;
using namespace std;
typedef long long LL;
int p,np,last=1,cnt=1,l[maxn<<1],fa[maxn<<1],ch[maxn<<1][26],sz[maxn<<1];
LL ans;
char s[maxn];
void ins(int c){
    p=last; np=++cnt; last=np; 
    l[np]=l[p]+1;
    for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
    if(!p) fa[np]=1;
    else{
        int q=ch[p][c];
        if(l[p]+1==l[q]) fa[np]=q;
        else{
            int nq=++cnt; l[nq]=l[p]+1;
            memcpy(ch[nq],ch[q],sizeof(ch[q]));
            fa[nq]=fa[q]; fa[q]=fa[np]=nq;
            for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
         }
    }
    sz[np]=1;
}
void cul(){
    static int c[maxn],sa[maxn];
    int n=strlen(s);
    for(int i=1;i<=cnt;i++) c[l[i]]++;
    for(int i=1;i<=cnt;i++) c[i]+=c[i-1];
    for(int i=1;i<=cnt;i++) sa[c[l[i]]--]=i;
    for(int i=cnt;i>=1;i--){
        sz[fa[sa[i]]]+=sz[sa[i]];
        if(sz[sa[i]]>=2) ans=max(ans,(LL)sz[sa[i]]*l[sa[i]]);
    }
}
int main()
{
    scanf("%s",s);
    for(int i=0;s[i]!=\0;i++) ins(s[i]-a);
    cul();
    printf("%lld\n",ans);
    return 0;
}
后缀自动机

 

6.回文自动机

技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=300000+29;
using namespace std;
typedef long long LL;
char s[maxn];
namespace pam{
    struct Node{
        int len,sz;
        Node *par,*to[26];
        Node(){}
        Node(int len,Node *par=NULL):len(len),par(par){}
    }pool[maxn],*pis,*last,*rt[2];  
    
    void init(){
        pis=pool;
        rt[1]=new(pis++) Node(-1);
        rt[0]=new(pis++) Node(0,rt[1]);
        last=rt[1]->par=rt[1];
    }
    
    void extend(char *s,int n){
        Node* p=last;
        int c=s[n]-a;
        while(s[n-p->len-1]!=s[n]) p=p->par;
        if(!p->to[c]){
            Node *q=p->par;
            while(s[n-q->len-1]!=s[n]) q=q->par;
            p->to[c]=new(pis++) Node(p->len+2,q->to[c]?q->to[c]:rt[0]);
        }
        (last=p->to[c])->sz++;   
    }
    
    LL query(){
        LL ans=0;
        for(Node *p=pis-1; p!=pool; --p){
            p->par->sz+=p->sz;
            ans=max(ans,(LL)p->sz*p->len);
        }
        return ans;
    }  
}
int main()
{
   scanf("%s",s+1);
   pam::init();
   for(int i=1;s[i];i++){
       pam::extend(s,i);    
   }
   cout<<pam::query()<<endl;
   return 0;
}
回文自动机

 

字符串算法模板

标签:ons   algorithm   null   ide   build   后缀   min   ast   name   

原文地址:http://www.cnblogs.com/Achenchen/p/7474939.html

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