shift-and 算法初体验

shift-and算法的思想与kmp的算法思想类似,更简单

shift-and算法的适用范围是字符串匹配,但是此时模板串可以有很多个

直接拿模板题:hdu 5972 来说

题意:模式串有n位长度,n的大小是1000,每一位有x种选择,x的大小是10,也就是说模式串组合的话,大约可以组合出来10^1000种,于是普通的AC自动机什么的都GG了

shift-and是用bitset实现的,bitset是高端卡常题的宠儿,很少被我使用的经典STL

bitset可以想象成是vector容器,对于每一位只占用一个字节,也就是char型的八分之一的大小,于是省时又省空间

需要注意的是:假设声明bitset<int>foo;  那么foo[0]会显示在最右端,foo[n-1]会显示在最左端,刚好与普通的数组是相反的

foo.set()  全部设置为1

foo.reset()   全部设置为0

foo.set(x)    将foo[x]设置成1

foo.reset(x)  将foo[x]设置成0

按照代码理解吧~

首先是输入部分


build() 函数的作用是构建bitset ,  solve() 函数就是解决问题 具体怎么实习的后面介绍

首先我声明的bitset长度就是n的大小,10个bitset,记录的就是每一个数字可以出现在第几位

接下来ans也是一个bitset,他记录我们在处理过程中的结果

每一步 我们就将当前位直接置1,询问这一位是否可以匹配,与前面的,当前面也可以,这一步也可以的话,那么这一个就匹配成功

代码如下:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<vector>
    #include<bitset>

    using namespace std;

    const int maxn = 1003;

    int n , x , num;
    vector<int>V[maxn];
    char s[5000006];
    bitset<maxn>b[13] , ans;

    void build()
    {
        for(int i=0; i<10; i++)
        {
            b[i].reset();
        }
        ans.reset();
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<V[i].size(); j++)
            {
                b[V[i][j]].set(i);
            }
        }
    //    for(int i=0; i<10; i++)
    //    {
    //        cout<<b[i]<<endl;
    //    }
    }

    void solve()
    {
        int len = strlen(s);
        for(int i=0; i<len; i++)
        {
            int tmp = s[i]-'0';
            ans = ans<<1;
            ans.set(0);
            ans = ans&b[tmp];
            if(ans[n-1]==1)
            {
                  char ttmp = s[i+1];
                  s[i+1] = '';
                  puts(s+i+1-n);
                  s[i+1] = ttmp;
            }
        }
    }

    void init()
    {
        for(int i=0; i<n; i++)
        {
            V[i].clear();
        }
    }

    int main()
    {
        while( scanf("%d" , &n) != EOF )
        {
            init();
            for(int i=0; i<n; i++)
            {
                scanf("%d" , &x);
                for(int j=1; j<=x; j++)
                {
                    scanf("%d" , &num);
                    V[i].push_back(num);
                }
            }
            scanf("%s" , s);
            build();
            solve();
        }


        return 0;
    }
原文地址:https://www.cnblogs.com/Flower-Z/p/9772534.html