字符串题模板集合

后缀数组

//by zzq
//改进后的后缀数组模板 
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 2333333
#define P 20
int n,k,sa[SZ],t[SZ],rank[SZ],qzh[SZ],tmpsa[SZ],tmpr[SZ],h[SZ];
char s[SZ];
bool same(int a,int b,int p) {return t[a]==t[b]&&t[a+p]==t[b+p];}
void getsa(int m=500)
{
    s[++n]=0;
    for(int i=0;i<n;i++) rank[i]=s[i], ++qzh[rank[i]];
    for(int i=1;i<m;i++) qzh[i]+=qzh[i-1];
    for(int i=n-1;i>=0;i--) sa[--qzh[rank[i]]]=i;
    for(int j=1;j<=n;j<<=1)
    {
        int cur=-1;
        for(int i=n-j;i<n;i++) tmpsa[++cur]=i;
        for(int i=0;i<n;i++) if(sa[i]>=j) tmpsa[++cur]=sa[i]-j;
        for(int i=0;i<n;i++) tmpr[i]=rank[tmpsa[i]];
        for(int i=0;i<m;i++) qzh[i]=0;
        for(int i=0;i<n;i++) ++qzh[tmpr[i]];
        for(int i=1;i<m;i++) qzh[i]+=qzh[i-1];
        for(int i=n-1;i>=0;i--) t[i]=rank[i], sa[--qzh[tmpr[i]]]=tmpsa[i];
        m=0;
        for(int i=0;i<n;i++)
            rank[sa[i]]=(i>0&&same(sa[i],sa[i-1],j))?m:++m;
        ++m;
    }
    for(int i=0;i<n;i++) rank[sa[i]]=i;
    int p=0;
    for(int i=0;i<n;i++)
    {
        if(p) --p;
        int ls=sa[rank[i]-1];
        while(s[ls+p]==s[i+p]) p++;
        h[rank[i]]=p;
    }
    --n;
    for(int i=1;i<=n;i++) sa[i-1]=sa[i];
    for(int i=0;i<n;i++) rank[sa[i]]=i;
    for(int i=2;i<=n;i++) h[i-1]=h[i];
    h[n]=sa[n]=0;
}
int log2[SZ],minn[SZ][P];
void getst()
{
    for(int i=0;i<n;i++) minn[i][0]=h[i];
    for(int i=1;i<=n;i++)
    {
        int t=0;
        while((1<<t)<=i) ++t;
        log2[i]=t-1;
    }
    for(int j=1;j<P;j++)
    {
        for(int i=0;i<n;i++)
        {
            if(i+(1<<j)<=n) minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
            else minn[i][j]=-2333;
        }
    }
}
int gmin(int a,int b)
{
    int l2=log2[b-a+1];
    return min(minn[a][l2],minn[b-(1<<l2)+1][l2]);
}
int lcp(int a,int b)
{
    if(a==b) return n-a;
    if(rank[a]>rank[b]) swap(a,b);
    return gmin(rank[a]+1,rank[b]);
}
int main()
{
    scanf("%s",s);
    n=strlen(s); getsa(); getst();
    while(1)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",lcp(a,b));
    }
}

hash+kmp(搭配风味更佳)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <algorithm>
using namespace std;
#define SZ 2333333
typedef long long ll;
ll MOD=1000000007,cm[SZ],cmn[SZ];
ll qp(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%MOD;
        a=a*a%MOD; b>>=1;
    }
    return ans;
}
struct HashKMP
{
char s[SZ+1]; int n;
ll hash[SZ+1];
void pre()
{
    n=strlen(s);
    for(int i=n-1;i>=0;i--) hash[i]=(hash[i+1]+cm[n-1-i]*(s[i]-'a'+1)%MOD)%MOD;
}
ll ghash(int l,int r)
{
    return ((hash[l]-hash[r+1])*cmn[n-1-r]%MOD+MOD)%MOD;
}
int next[SZ+3];
void gnext()
{
    next[0]=-1;
    int j=-1;
    for(int i=1;s[i];i++)
    {
        while(j!=-1&&s[i]!=s[j+1]) j=next[j];
        if(s[i]==s[j+1]) ++j;
        next[i]=j;
    }
}
void kmp(char* a)
{
    int j=-1;
    for(int i=0;a[i];i++)
    {
        while(j!=-1&&s[j+1]!=a[i]) j=next[j];
        if(s[j+1]==a[i]) ++j;
        //do sth
        printf("%d w %d\n",i,j);
    }
}
}ha;
void getcm()
{
    cm[0]=cmn[0]=1; ll gg=qp(31,MOD-2);
    for(int i=1;i<=1234567;i++) cm[i]=cm[i-1]*31%MOD;
    for(int i=1;i<=1234567;i++) cmn[i]=cmn[i-1]*gg%MOD;
}

char b[SZ+3];
int main()
{
    getcm();
    scanf("%s",ha.s);
    ha.pre();
    scanf("%s",b);
    ha.gnext();
    ha.kmp(b);
}

后缀自动机+序列自动机

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
int MOD=998244353;
#define SZ 4008
#define S 26 //字符集
struct AM
{
int rot,ch[SZ][S],C,cnt[SZ];
};
struct SeqAM: public AM
{
int par[SZ],lst[S];
SeqAM()
{
    C=rot=1;
    for(int i=0;i<S;i++) lst[i]=rot;
}
void ins(char c)
{
    ++C; par[C]=lst[c];
    for(int i=0;i<S;i++)
    {
        for(int g=lst[i];g&&!ch[g][c];g=par[g]) ch[g][c]=C;
    }
    lst[c]=C;
}
void getcnt()
{
    for(int i=1;i<=C;i++) cnt[i]=1;
    for(int i=C;i>=1;i--)
    {
        for(int j=0;j<S;j++) cnt[i]+=cnt[ch[i][j]], cnt[i]%=MOD;
    }
}
}SeqA,SeqB;
struct SufAM: public AM
{
int ml[SZ],fail[SZ],lst,cl,qzh[SZ],od[SZ];
SufAM() {C=lst=rot=1; cl=0;}
void ins(char c)
{
    int x=++C,len=++cl,p=lst;
    lst=x; ml[x]=len;
    for(;p&&!ch[p][c];p=fail[p]) ch[p][c]=x;
    if(!p) fail[x]=rot;
    else if(ml[ch[p][c]]==ml[p]+1) fail[x]=ch[p][c];
    else
    {
        int chh=ch[p][c],cm=++C;
        ml[cm]=ml[p]+1; fail[cm]=fail[chh];
        for(int i=0;i<S;i++) ch[cm][i]=ch[chh][i];
        fail[chh]=fail[x]=cm;
        for(;ch[p][c]==chh;p=fail[p]) ch[p][c]=cm;
    }
}
void getcnt()
{
    for(int i=0;i<SZ;i++) qzh[i]=0;
    for(int i=1;i<=C;i++) qzh[ml[i]]++;
    for(int i=1;i<SZ;i++) qzh[i]+=qzh[i-1];
    for(int i=1;i<=C;i++) od[qzh[ml[i]]--]=i;
    for(int i=1;i<=C;i++) cnt[i]=1;
    for(int i=C;i>=1;i--)
    {
        for(int j=0;j<S;j++) cnt[od[i]]+=cnt[ch[od[i]][j]], cnt[od[i]]%=MOD;
    }
}
}SufA,SufB;

AC自动机

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 1000099
int rot=1,ch[SZ][29],fail[SZ],cnt[SZ],e=1;
void insert(char* s)
{
    int cur=rot;
    for(int i=0;s[i];i++)
    {
        int c=s[i]-'a';
        if(!ch[cur][c]) ch[cur][c]=++e;
        cur=ch[cur][c];
    }
    cnt[cur]++;
}
int qs[SZ],h=0,t=0;
void bfail()
{
    h=t=0; fail[rot]=rot;
    for(int i=0;i<26;i++)
    {
        if(!ch[rot][i]) 
        {
            ch[rot][i]=rot; continue;
        }
        fail[ch[rot][i]]=rot;
        qs[t++]=ch[rot][i];
    }
    while(h!=t)
    {
        int cur=qs[h++];
        for(int c=0;c<26;c++)
        {
            if(!ch[cur][c]) ch[cur][c]=ch[fail[cur]][c];
            else
            {
                fail[ch[cur][c]]=ch[fail[cur]][c];
                qs[t++]=ch[cur][c];
            }
        }
    }
}
int match(char* s)
{
    int cur=rot,ans=0;
    for(int i=0;s[i];i++)
    {
        int c=s[i]-'a'; cur=ch[cur][c];
        for(int f=cur;f!=rot;f=fail[f]) ans+=cnt[f], cnt[f]=0;
    }
    return ans;
}

int n,T;
char str[SZ];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        rot=e=1;
        memset(ch,0,sizeof(ch));
        memset(fail,0,sizeof(fail));
        memset(cnt,0,sizeof(cnt));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            insert(str);
        }
        bfail();
        scanf("%s",str);
        printf("%d\n",match(str));
    }
}

manacher

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define SZ 666666
int p[SZ];
char str[SZ];
void manacher()
{
    int ml=0,id;
    for(int i=0;str[i];i++)
    {
        if(ml>i) p[i]=min(p[2*id-i],p[id]+id-i);
        else p[i]=1;
        while(i>=p[i]&&str[i+p[i]]==str[i-p[i]]) ++p[i];
        if(p[i]+i>ml) ml=p[i]+i, id=i;
    }
}
char s[SZ];
void init()
{
    str[0]='$'; int n=1;
    for(int i=0;s[i];i++) str[n++]=s[i], str[n++]='$';
    str[n]=0;
}
int main()
{
    while(gets(s))
    {
        if(!s[0]) continue;
        init(); manacher();
        int ans=0;
        for(int i=0;str[i];i++) ans=max(ans,p[i]);
        printf("%d\n",ans-1);
    }
    return 0;
}

回文树

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <limits>
#include <set>
#include <map>
using namespace std;
struct PTree
{
#define SZ 666666
int ch[SZ][26],len[SZ],fail[SZ],cnt[SZ],s[SZ],cl,an,lst;
int addn(int l) {len[an]=l; return an++;}
PTree()
{
    cl=an=lst=0;
    memset(ch,0,sizeof(ch));
    addn(0); addn(-1);
    fail[0]=1; s[0]=-233;
}
int gfail(int x,int l)
{
    while(s[l-len[x]-1]!=s[l]) x=fail[x];
    return x;
}
void add(int c)
{
    s[++cl]=c;
    int cp=gfail(lst,cl);
    if(!ch[cp][c])
    {
        int nn=addn(len[cp]+2);
        fail[nn]=ch[gfail(fail[cp],cl)][c];
        ch[cp][c]=nn;
    }
    cnt[lst=ch[cp][c]]++;
}
void getcnt()
{
    for(int i=an-1;i>=2;i--) cnt[fail[i]]+=cnt[i];
}
}pt;

char s[SZ];
int main()
{
    scanf("%s",s);
    for(int i=0;s[i];i++) pt.add(s[i]-'a');
    pt.getcnt();
    long long ans=0;
    for(int i=2;i<=pt.an;i++) ans=max(ans,pt.len[i]*(long long)pt.cnt[i]);
    printf("%lld\n",ans);
}

本来这篇文章是想放一些字符串题目,在前面整一下模板...没想到整了这么长...就下一篇文章放题目好了。

posted @ 2016-06-15 22:30  fjzzq2002  阅读(452)  评论(0编辑  收藏  举报