• 排列乘法


    假设我们已有6个元素{a,b,c,d,e,f},我们要将这6个元素的一个序列改成另一个序列

      比如:a b c d e f 

      --->  c d f b e a 

    我们可以采用“循环记号”标记上面的改变

      (acf)(bd)

    表示为a-->c,c-->f,f-->a,b-->d,d-->b

    在一个排列之后我们又可以应用另一个排序,我们可以将两个排列相乘

    | a b c d e f |     | a b c d e f |     | a b c d e f |

    |                  |  * |                 |  = |                  |

    | c d f b e a |     | b d c a f e |     | c a e b f d |

    显然排列乘法不满足交换率,采用循环记号,我们可以将上面的乘式写为:

    (acf)(bd)(abd)(ef)=(acefb)

    因此我们可以处理多项乘式相乘的结果。

    循环扫描

    算法流程

      E1.将乘法式中的右括号替换为与之对应的左括号后一个的字符

      E2.从左到右找出没有被标记过的元素(所有元素都被标记了则算法结束),将该元素赋给Start,输出左括号以及该元素,并标记该元素

      E3.将当前的算式的后一个元素赋给Current

      E4.向右扫描算式,如果找到Current的元素,则返回E3.否则扫描至算式末尾

      E5.判断Current==Start,如果不相等,标记Current,找到Current在算式最开始出现的地方.返回E3.

      E6.输出右括号,返回E2

    证明

      针对每一个未标记的元素根据算式遍历找到最终的替换元素,然后标记该元素,显然可以找出所有元素最终替换元素,复杂度为O(N*L)

    代码实现

    void ChangeStr(char *str)
    {
        int i;
        char pre;
        for(i=0;str[i]!='';++i)
        {
            if(str[i]=='(')
            {
                pre=str[i+1];
            }
            if(str[i]==')')
            {
                str[i]=pre;
            }
        }
    }
    int FindAnyEle(char *src,char *flag,char *start)
    {
        int i;
        for(i=0;src[i]!='';++i)
        {
            if(src[i]=='(')
            {
                continue;
            }
            if(!flag[src[i]-'a'])
            {    
                *start=src[i];
                printf("(%c",src[i]);
                flag[src[i]-'a']=1;
                return i;
            }
        }
        return -1;
    }
    int FindNextEle(char *src,char key,int from)
    {
        int i;
        for(i=from+1;src[i]!='';++i)
        {
            if(src[i]==key)
            {
                return i;
            }
        }
        return -1;
    }
    int FindOneEle(char *src,char *flag,char key)
    {
        int i;
        for(i=0;src[i]!='';++i)
        {
            if(src[i]==key)
            {
                printf("%c",key);
                flag[src[i]-'a']=1;
                return i;
            }
        }
        return -1;
    }
    void PermutationMul(int EleNum,char *SrcMulStr)
    {
        ChangeStr(SrcMulStr);
        char *Flag=(char *)malloc(EleNum*sizeof(char));
        int i,id;
        char Start,Current;
        for(i=0;i<EleNum;++i)
        {
            Flag[i]=0;
        }
        id=FindAnyEle(SrcMulStr,Flag,&Start);
        while(~id)
        {
            while(~id)
            {
                Current=SrcMulStr[id+1];
                id=FindNextEle(SrcMulStr,Current,id+1);
            }
            if(Current!=Start)
            {
                id=FindOneEle(SrcMulStr,Flag,Current);
            }
            else
            {
                printf(")");
                id=FindAnyEle(SrcMulStr,Flag,&Start);
            }
        }
        free(Flag);
        printf("
    ");
    }
    View Code

    逆序迭代

    算法流程

      E1.初始化,对于1<=i<=N,将T[i]=i;T[i]表示i元素将被T[i]元素替换

      E2.从右往左读取输入算式,读取下一个元素,如果输入结束,算法则也结束,如果元素为')',置Z=0重复E2;如果为‘(’,转去E4,否则转到E3

      E3.交换Z与T[i],如果此时T[i]==0,将i赋值给j;返回E2

      E4.将T[j]赋为Z;返回E2

    证明

      一遍扫描迭代更新T[i]最终被替换的值,因为我们要找到最终被替换的值,所以要从右往左读,如果从左往右读可以迭代求出最终替换项被替换的值,比如最终T[1]=3,从右往左读的话,表示最终1要被3代替,从左往右读的话,表示最终3是被1代替.

      显然通过逆序迭代每对括号,更新每对括号包含的替换信息,最终可以求出每个元素被替代的值,复杂度为O(L)

    代码实现

    void PermutationMulEx(int EleNum,char *SrcMulStr)
    {
        int i,j,Z,Len,t;
        char *T=(char *)malloc(EleNum*sizeof(char));
        for(i=0;i<EleNum;++i)
        {
            T[i]=i;
        }
        Len=strlen(SrcMulStr);
        for(i=Len-1;i>=0;--i)
        {
            if(SrcMulStr[i]==')')
            {
                Z=-1;
                continue;
            }
            if(SrcMulStr[i]=='(')
            {
                T[j]=Z;
            }
            else
            {
                t=Z;
                Z=T[SrcMulStr[i]-'a'];
                T[SrcMulStr[i]-'a']=t;
                if(T[SrcMulStr[i]-'a']==-1)
                {
                    j=SrcMulStr[i]-'a';
                }
            }
        }
        for(i=0;i<EleNum;++i)
        {
            printf("%d ",T[i]);
        }
        printf("
    ");
        free(T);
    }
    View Code
  • 相关阅读:
    Python爬虫_分布式爬虫
    Python爬虫_selenium
    Python爬虫_scrapy框架
    Python爬虫_高性能爬取
    Python爬虫_三种数据解析方式
    Python爬虫_requests模块
    Django
    Python爬虫相关基础概念
    MySQL 多表结构的创建与分析
    mysql
  • 原文地址:https://www.cnblogs.com/NoSoul/p/3303123.html
Copyright © 2020-2023  润新知