zoukankan      html  css  js  c++  java
  • 1.kmp

    /*
    kmp
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    #define MAXN 1024//字符串长度
    
    int _next[MAXN];
    
    void GetNext(char t[]){//求next数组
        int j,k,len;
        j=0;//从0开始,首先求_next[1]
        k=-1;//比较指针
        _next[0]=-1;//初始值-1
        len=strlen(t);
        while(j<len){
            if(k==-1||t[j]==t[k]){//指针到头了,或者相等
                ++j;
                ++k;
                _next[j]=k;//此句可由优化替代
                /*优化(求匹配位置时可用)
                if(t[j]!=t[k])_next[j]=k;
                else _next[j]=_next[k];
                //*/
            }
            else k=_next[k];
        }
    }
    
    int KMPIndex(char s[],char t[]){//求子串首次出现在主串中的位置
        int i,j,lens,lent;
        i=j=0;
        lens=strlen(s);
        lent=strlen(t);
    
        while(i<lens&&j<lent){
            if(j==-1||s[i]==t[j]){
                ++i;
                ++j;
            }
            else j=_next[j];
        }
        if(j>=lent)return i-lent;
        else return -1;
    }
    
    int KMPCount(char s[],char t[]){//统计子串在主串中的出现次数,可重叠
        int i,j,lens,lent,cnt;
        i=j=0;
        lens=strlen(s);
        lent=strlen(t);
        cnt=0;
    
        while(i<lens){
            if(j==-1||s[i]==t[j]){
                ++i;
                ++j;
            }
            else j=_next[j];
            if(j==lent)++cnt;
        }
        return cnt;
    }
    
    void KMPCount2(char t[]){//统计单串中从某个位置以前有多少重复的串
        int i,lent,tmp;
        lent=strlen(t);
    
        for(i=2;i<=lent;++i){
            tmp=i-_next[i];//tmp是0...i-1这一串的最小循环节长度
            if(i%tmp==0&&i/tmp>1)
                printf("	位置:%d 个数:%d
    ",i,i/tmp);
        }
    }
    
    int main(){
        char str1[MAXN],str2[MAXN];
        int i,len2;
        printf("输入主串、子串:");
        while(~scanf("%s%s",str1,str2)){
            GetNext(str2);//求子串的next数组
    
            //输出next数组的值
            printf("next:");
            len2=strlen(str2);
            for(i=0;i<=len2;++i)
                printf("%d ",_next[i]);
            printf("
    ");
    
            printf("首次出现位置:%d
    ",KMPIndex(str1,str2));
    
            printf("子串在主串中的出现次数:%d
    ",KMPCount(str1,str2));
    
            printf("子串中的重复串:
    ");
            KMPCount2(str2);
    
            printf("输入主串、子串:");
        }
        return 0;
    }
    View Code

    2.扩展kmp

    /*
    扩展kmp
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    #define MaxSize 1024
    
    int _next[MaxSize],extend[MaxSize];
    
    //扩展kmp
    //next[i]:x[i...m-1]与x[0...m-1]的最长公公前缀
    //extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀
    void pre_EKMP(char x[],int m,int _next[]){//m长度
        _next[0]=m;
        int j=0;
        while(j+1<m&&x[j]==x[j+1])j++;
        _next[1]=j;
        int k=1;
        for(int i=2;i<m;i++){
            int p=_next[k]+k-1;
            int L=_next[i-k];
            if(i+L<p+1)_next[i]=L;
            else{
                j=max(0,p-i+1);
                while(i+j<m&&x[i+j]==x[j])j++;
                _next[i]=j;
                k=i;
            }
        }
    }
    
    void EKMP(char x[],int m,char y[],int n,int _next[],int extend[]){//x子串,m子串长度,y主串,n主串长度
        pre_EKMP(x,m,_next);
        int j=0;
        while(j<n&&j<m&&x[j]==y[j])j++;
        extend[0]=j;
        int k=0;
        for(int i=1;i<n;i++){
            int p=extend[k]+k-1;
            int L=_next[i-k];
            if(i+L<p+1)extend[i]=L;
            else{
                j=max(0,p-i+1);
                while(i+j<n&&j<m&&y[i+j]==x[j])j++;
                extend[i]=j;
                k=i;
            }
        }
    }
    /*
    子串  :a b a b
    主串  :a b a b a c
    next  :4 0 2 0
    extend:4 0 3 0 1 0
    */
    
    int main(){
        char str1[32],str2[32];//子串,主串
        int i,len1,len2;//子串长度,主串长度
        scanf("%s%s",str1,str2);
        len1=strlen(str1);
        len2=strlen(str2);
        EKMP(str1,len1,str2,len2,_next,extend);
        for(i=0;i<len1;++i)
            printf("%d ",_next[i]);
        printf("
    ");
        for(i=0;i<len2;++i)
            printf("%d ",extend[i]);
        printf("
    ");
    
        return 0;
    }
    View Code

    3.Manacher

    /*
    Manacher
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    //求最长回文子串
    const int MAXN=110010;
    char Ma[MAXN*2];
    int Mp[MAXN*2];
    
    void Manacher(char s[],int len){
        int l=0;
        Ma[l++]='$';
        Ma[l++]='#';
        for(int i=0;i<len;i++){
            Ma[l++]=s[i];
            Ma[l++]='#';
        }
        Ma[l]=0;
        int mx=0,id=0;
        for(int i=0;i<l;i++){
            Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
            while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++;
            if(i+Mp[i]>mx){
                mx=i+Mp[i];
                id=i;
            }
        }
    }
    /*
    abaaba
    i:    0 1 2 3 4 5 6 7 8 9 10 11 12 13
    Ma[i]:$ # a # b # a # a # b  #  a  #
    Mp[i]:1 1 2 1 4 1 2 7 2 1 4  1  2  1
    */
    
    char s[MAXN];
    int main(){
        while(scanf("%s",s)==1){
            int len=strlen(s);
            Manacher(s,len);
            int ans=0;
            for(int i=0;i<2*len+2;i++)
                ans=max(ans,Mp[i]-1);
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    4.ac自动机

    /*
    ac自动机模板
    n个关键字,1段描述,求描述中出现了多少关键字
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    
    struct Trie{
        int next[500010][26],fail[500010],end[500010];
        int root,L;
        int newnode(){
            for(int i=0;i<26;i++)
                next[L][i]=-1;
            end[L++]=0;
            return L-1;
        }
        void init(){
            L=0;
            root=newnode();
        }
        void insert(char buf[]){
            int len=strlen(buf);
            int now=root;
            for(int i=0;i<len;i++){
                if(next[now][buf[i]-'a']==-1)
                    next[now][buf[i]-'a']=newnode();
                now=next[now][buf[i]-'a'];
            }
            end[now]++;
        }
        void build(){
            queue<int>Q;
            fail[root]=root;
            for(int i=0;i<26;i++)
                if(next[root][i]==-1)
                    next[root][i]=root;
                else{
                    fail[next[root][i]]=root;
                    Q.push(next[root][i]);
                }
            while(!Q.empty()){
                int now=Q.front();
                Q.pop();
                for(int i=0;i<26;i++)
                    if(next[now][i]==-1)
                        next[now][i]=next[fail[now]][i];
                    else{
                        fail[next[now][i]]=next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
            }
        }
        int query(char buf[]){
            int len=strlen(buf);
            int now=root;
            int res=0;
            for(int i=0;i<len;i++){
                now=next[now][buf[i]-'a'];
                int temp=now;
                while(temp!=root){
                    res+=end[temp];
                    end[temp]=0;
                    temp=fail[temp];
                }
            }
            return res;
        }
        void debug(){
            for(int i=0;i<L;i++){
                printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
                for(int j=0;j<26;j++)
                    printf("%2d",next[i][j]);
                printf("]
    ");
            }
        }
    };
    
    char buf[1000010];
    Trie ac;
    
    int main(){
        int T;
        int n;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            ac.init();
            for(int i=0;i<n;i++){
                scanf("%s",buf);
                ac.insert(buf);
            }
            ac.build();
            scanf("%s",buf);
            printf("%d
    ",ac.query(buf));
        }
        return 0;
    }
    View Code

    5.trie树(字典树)

    c.动态开辟:

    /*
    trie树(字典树)
    动态开辟
    */
    #include<iostream>
    #include<string.h>
    using namespace std;
    
    const int MAX=26;
    struct Trie
    {
        Trie *next[MAX];
        int v;   //根据需要变化,1代表无此单词,-1代表有此单词
    };
    Trie *root=new Trie;
    
    void createTrie(char *str)
    {
        int len = strlen(str);
        Trie *p = root, *q;
        for(int i=0; i<len; ++i)
        {
            int id = str[i]-'a';
            if(p->next[id] == NULL)
            {
                // q = (Trie *)malloc(sizeof(Trie));
                q = new Trie;
                q->v = 1;    //初始v==1
                for(int j=0; j<MAX; ++j)
                    q->next[j] = NULL;
                p->next[id] = q;
            }
            p = p->next[id];
        }
        p->v = -1;   //若为结尾,则将v改成-1表示
    }
    int findTrie(char *str)
    {
        int len = strlen(str);
        Trie *p = root;
        for(int i=0; i<len; ++i)
        {
            int id = str[i]-'a';
            p = p->next[id];
            if(p == NULL)   //若为空集,表示不存以此为前缀的串
                return 0;
            if(p->v == -1)   //字符集中已有串是此串的前缀
                return 1;
        }
        return 2;   //此串是字符集中某串的前缀
    }
    int deleteTrie(Trie* T)
    {
        int i;
        if(T==NULL)
            return 0;
        for(i=0; i<MAX; i++)
        {
            if(T->next[i]!=NULL)
                deleteTrie(T->next[i]);
        }
        //free(T);
        delete(T);
        return 0;
    }
    int main()
    {
        char str[20];
        int i;
        for(i=0; i<MAX; i++)
            root->next[i]=NULL;
    
        cout<<"输入串1:";
        cin>>str;
        createTrie(str);
        cout<<"输入串2:";
        cin>>str;
        cout<<findTrie(str)<<endl;
        return 0;
    }
    View Code

    c2.静态数组:抽空补上。

    6.后缀数组

    c.DA

    /*
    后缀数组
    DA
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MAXN=20010;
    int t1[MAXN],t2[MAXN],c[MAXN];
    bool cmp(int *r,int a,int b,int l){
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    
    void da(int str[],int sa[],int rank[],int height[],int n,int m){
        n++;
        int i,j,p,*x=t1,*y=t2;
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[i]=str[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(j=1;j<=n;j<<=1){
            p=0;
            for(i=n-j;i<n;i++)y[p++]=i;
            for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
            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]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
            if(p>=n)break;
            m=p;
        }
        int k=0;
        n--;
        for(i=0;i<=n;i++)rank[sa[i]]=i;
        for(i=0;i<n;i++){
            if(k)k--;
            j=sa[rank[i]-1];
            while(str[i+k]==str[j+k])k++;
            height[rank[i]]=k;
        }
    }
    
    int rank[MAXN],height[MAXN];
    int RMQ[MAXN];
    int mm[MAXN];
    int best[20][MAXN];
    void initRMQ(int n){
        mm[0]=-1;
        for(int i=1;i<=n;i++)
            mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
        for(int i=1;i<=n;i++)best[0][i]=i;
        for(int i=1;i<=mm[n];i++)
            for(int j=1;j+(1<<i)-1<=n;j++){
                int a=best[i-1][j];
                int b=best[i-1][j+(1<<(i-1))];
                if(RMQ[a]<RMQ[b])best[i][j]=a;
                else best[i][j]=b;
            }
    }
    
    int askRMQ(int a,int b){
        int t;
        t=mm[b-a+1];
        b-=(1<<t)-1;
        a=best[t][a];b=best[t][b];
        return RMQ[a]<RMQ[b]?a:b;
    }
    
    int lcp(int a,int b){
        a=rank[a];b=rank[b];
        if(a>b)swap(a,b);
        return height[askRMQ(a+1,b)];
    }
    char str[MAXN];
    int r[MAXN];
    int sa[MAXN];
    
    int main(){
        while(scanf("%s",str)==1){
            int len=strlen(str);
            int n=2*len+1;
            for(int i=0;i<len;i++)r[i]=str[i];
            for(int i=0;i<len;i++)r[len+1+i]=str[len-1-i];
            r[len]=1;
            r[n]=0;
            da(r,sa,rank,height,n,128);
            for(int i=1;i<=n;i++)RMQ[i]=height[i];
            initRMQ(n);
            int ans=0,st;
            int tmp;
            for(int i=0;i<len;i++){
                tmp=lcp(i,n-i);
                if(2*tmp>ans){
                    ans=2*tmp;
                    st=i-tmp;
                }
                tmp=lcp(i,n-i-1);
                if(2*tmp>ans){
                    ans=2*tmp-1;
                    st=i-tmp+1;
                }
            }
            str[st+ans]=0;
            printf("%s
    ",str+st);
        }
        return 0;
    }
    View Code

    c2.DC3

    /*
    后缀数组
    DC3
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    const int MAXN=2010;
    #define F(x) ((x)/3+((x)%3==1?0:tb))
    #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
    int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3];
    int c0(int *r,int a,int b){
        return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];
    }
    int c12(int k,int *r,int a,int b){
        if(k==2)
            return r[a]<r[b]||(r[a]==r[b]&&c12(1,r,a+1,b+1));
        else return r[a]<r[b]||(r[a]==r[b]&&wv[a+1]<wv[b+1]);
    }
    void sort(int *r,int *a,int *b,int n,int m){
        int i;
        for(i=0;i<n;i++)wv[i]=r[a[i]];
        for(i=0;i<m;i++)wss[i]=0;
        for(i=0;i<n;i++)wss[wv[i]]++;
        for(i=1;i<m;i++)wss[i]+=wss[i-1];
        for(i=n-1;i>=0;i--)
            b[--wss[wv[i]]]=a[i];
    }
    void dc3(int *r,int *sa,int n,int m){
        int i,j,*rn=r+n;
        int *san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
        r[n]=r[n+1]=0;
        for(i=0;i<n;i++)if(i%3!=0)wa[tbc++]=i;
        sort(r+2,wa,wb,tbc,m);
        sort(r+1,wb,wa,tbc,m);
        sort(r,wa,wb,tbc,m);
        for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
            rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
        if(p<tbc)dc3(rn,san,tbc,p);
        else for(i=0;i<tbc;i++)san[rn[i]]=i;
        for(i=0;i<tbc;i++)if(san[i]<tb)wb[ta++]=san[i]*3;
        if(n%3==1)wb[ta++]=n-1;
        sort(r,wb,wa,ta,m);
        for(i=0;i<tbc;i++)wv[wb[i]=G(san[i])]=i;
        for(i=0,j=0,p=0;i<ta&&j<tbc;p++)
            sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
        for(;i<ta;p++)sa[p]=wa[i++];
        for(;j<tbc;p++)sa[p]=wb[j++];
    }
    void da(int str[],int sa[],int rank[],int height[],int n,int m){
        for(int i=n;i<n*3;i++)
            str[i]=0;
        dc3(str,sa,n+1,m);
        int i,j,k=0;
        for(i=0;i<=n;i++)rank[sa[i]]=i;
        for(i=0;i<n;i++){
            if(k)k--;
            j=sa[rank[i]-1];
            while(str[i+k]==str[j+k])k++;
            height[rank[i]]=k;
        }
    }
    
    int main(){
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 3411 Paid Roads(DFS)
    POJ 1699 Best Sequence(DFS)
    Codeforces Round #191 (Div. 2)
    Windows && Linux 搭建python开发环境
    zabbix 源码编译安装
    智能运维基础设施
    Redis
    ubuntu16.04 安装 mysql
    Python必须知道的基础语法
    ubuntu && CentOS && RedHat 离线安装docker
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5361058.html
Copyright © 2011-2022 走看看