字符串板子

kmp

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+4;
char a[maxn],b[maxn];
int p[maxn];
int main(){
    scanf("%s",a+1);
    scanf("%s",b+1);
    int n=strlen(a+1),m=strlen(b+1);
    int j=0;
    for(int i=2;i<=m;i++) {
        while(j&&b[j+1]!=b[i]) j=p[j];
        if(b[j+1]==b[i]) j++;
        p[i]=j;
    }
    j=0;
    for(int i=1;i<=n;i++){
        while(j&&b[j+1]!=a[i]) j=p[j];
        if(b[j+1]==a[i]) j++;
        if(j==m){
            printf("%d\n",i-m+1);
        }
    }
    for(int i=1;i<=m;i++) printf("%d\n",p[i]);
}
kmp

 

AC自动机

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+4;
int tot=0;
struct node{
    int fail,next[26],tag;
}z[maxn];
inline void insert(char *s){
    int len=strlen(s);
    int now=0;
    for(int i=0;i<len;i++){
        int v=s[i]-'a';
        if(!z[now].next[v]) z[now].next[v]=++tot;
        now=z[now].next[v];
    }
    z[now].tag++;
}
inline void build_AC(){
    queue<int>q;
    for(int i=0;i<26;i++) {
        z[z[0].next[i]].fail=0;
        if(z[0].next[i]) q.push(z[0].next[i]);
    }
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=0;i<26;i++){
            if(z[now].next[i]){
                z[z[now].next[i]].fail=z[z[now].fail].next[i];
                q.push(z[now].next[i]);
            }else{
                z[now].next[i]=z[z[now].fail].next[i];
            }
        }
    }
}
inline int query(char *s){
    int len=strlen(s);
    int now=0,ans=0;
    for(int i=0;i<len;i++){
        now=z[now].next[s[i]-'a'];
        ans+=z[now].tag;
        z[now].tag=0;
    }
    return ans;
}

 

后缀数组:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+4;
struct node{
    int pos,x[2];//pos开始的位置是哪里,x[0]与x[1]存储用来基数排序的两个值 
    node(){}
    node(int a,int b,int c){
        pos=a;x[1]=b;x[0]=c;
    }
}x[maxn],sw[maxn];
char s[maxn];
int z[maxn],buf[maxn],n,rank[maxn],sa[maxn],height[maxn];
inline void count_sort(int upper){
    for(int a=0;a<=1;a++){
        memset(buf,0,sizeof(buf));
        for(int b=1;b<=n;b++) buf[x[b].x[a]]++;
        for(int b=1;b<=upper;b++) buf[b]+=buf[b-1];
        for(int b=n;b>=1;b--) sw[buf[x[b].x[a]]--]=x[b];
        for(int b=1;b<=n;b++) x[b]=sw[b];
    }
    int cnt=1;
    rank[x[1].pos]=1;
    for(int a=2;a<=n;a++) {
        if(x[a].x[0]==x[a-1].x[0]&&x[a].x[1]==x[a-1].x[1]) rank[x[a].pos]=cnt;
        else rank[x[a].pos]=++cnt;
    }
}
inline void calc_sa(){
    for(int a=1;a<=n;a++) x[a]=node(a,z[a],0);
    count_sort(1000000);//得到所有rank1[i]
    for(int a=1;a<=n;a<<=1){
        for(int b=1;b<=n;b++)
            x[b]=node(b,rank[b],a+b<=n?rank[a+b]:0);
        count_sort(1000000);
    }//rank[i]第i个后缀排名第几 
    for(int a=1;a<=n;a++) sa[rank[a]]=a;//sa[i]排名为i的后缀是第几个后缀 
    for(int a=1;a<=n;a++) {
        int l=height[rank[a-1]];
        if(l>0) l--;
        int p=sa[rank[a]-1];
        while(a+l<=n&&p+l<=n&&s[a+l]==s[p+l]) l++;
        height[rank[a]]=l;
    }
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    for(int i=1;i<=n;i++){
        z[i]=s[i];
    }
    calc_sa();
    for(int i=1;i<=n;i++)printf("%d ",sa[i]);
}

 

Manacher

#include<iostream>
#include<cmath>
#include<cstring>
#define maxn 51000100
using namespace std;
int n,hw[maxn],ans;
char a[maxn],s[maxn<<1];
void manacher()
{
    int maxright=0,mid;
    for(int i=1;i<n;i++)
    {
        if(i<maxright)
            hw[i]=min(hw[(mid<<1)-i],hw[mid]+mid-i);
        else
            hw[i]=1;
        for(;s[i+hw[i]]==s[i-hw[i]];++hw[i]);
        if(hw[i]+i>maxright)
        {
            maxright=hw[i]+i;
            mid=i;
        }
    }
}
void change()
{
    s[0]=s[1]='#';
    for(int i=0;i<n;i++)
    {
        s[i*2+2]=a[i];
        s[i*2+3]='#';
    }
    n=n*2+2;
    s[n]=0;
}
int main()
{
    scanf("%s",a);
    n=strlen(a);
    change();
    manacher();
    ans=1;
    for(int i=0;i<n;i++)
        ans=max(ans,hw[i]);
    printf("%d",ans-1);
    return 0; 
}

 

posted @ 2019-01-07 13:51  WiFiMonster  阅读(190)  评论(0编辑  收藏  举报